I. CAN Bus Real-Time Token Ring
1. Characteristics of the CAN bus
CAN bus (Controller Area Net) is a serial communication network that effectively supports distributed control. It was designed by Bosch in Germany for automotive monitoring and control systems. Due to its excellent characteristics and extremely high reliability, it has since been widely used for interconnecting industrial process monitoring equipment.
The CAN bus only defines Layer 1 (Physical Layer) and Layer 2 (Data Link Layer) of the ISO/OSI model, and its physical topology is shown in Figure 1. The main characteristics of the CAN bus are:
(1) Differential transmission is used, which has strong anti-interference ability;
(2) It adopts error detection measures such as short frame structure and CRC check, resulting in a low probability of error;
(3) It adopts a priority-based non-destructive bus arbitration technology, which can work in multi-master, one-to-one, one-to-many and global broadcast modes to transmit and receive data;
(4) The communication distance varies with the baud rate, with typical values of 10 km (5 kb/s) and 40 m (1 Mb/s).
2. Introduction to Token Bus
The logical topology of the token bus network is shown in Figure 2. All stations connected to the token bus logically form a loop, and each station knows its predecessor (PS) and successor (NS).
The token is actually a specially encoded control frame. Only one token is passed along the logical ring on the network. Only the station that receives the token can send data and then pass the token down the chain. During normal operation, the token is transmitted from one station to another according to the sequence number of the station address. In this way, the token is actually transmitted along the logical ring rather than the physical ring. The last station in the numerical sequence returns the token to the first station.
The advantage of the token communication mechanism is that only one pair of nodes are communicating in the network at any given time, completely eliminating the possibility of communication conflicts between multiple nodes.
II. SMC304 Motion Controller CAN Bus Token Ring and Commands
1. Communication mechanism of Leadshine CAN bus token network
The SMC304 motion controller can be connected to other SMC304 motion controllers or other Leadshine motion controllers via a CAN bus to form a multi-station CAN bus motion control system. A token communication mechanism is used to achieve data exchange between stations. Unlike typical token networks, Leadshine's CAN bus token network has a master station responsible for managing token transmission, preventing token loss, and thus improving communication reliability.
Four types of data can be sent on the Leadshine CAN bus real-time token network: bit, word, double word, and floating-point data. The communication process is as follows:
The first step is that the master station periodically sends the data in its register data table to all other stations; then it sends a token message to one of the slave stations. The second step is that after receiving the token, the slave station sends the data in its register data table to all other stations; then it sends a token release message to the master station. The third step is that after receiving a token release message from a slave station, the master station sends a token message to the next slave station; then it returns to the second step until all stations have completed sending their data. The fourth step is that the master station repeats the above process after the cycle time expires.
All of the above communication processes are performed in the background of the BASIC program and do not require user programming management.
Users need to first initialize the register data table used for data communication in the program, set the communication period, the number of nodes participating in the communication and the node number; define the data type to be communicated and the peer node number; and add a communication data end marker.
Then, by periodically querying the local registers in the program as needed, data from other nodes can be obtained; the register data table can be updated periodically, and the new data can be automatically sent to other nodes.
2. Communication commands for Leadshine CAN bus token network
1) Initialize the CAN communication data table parameters: SMCCanRegTableInit short SMCCanRegTableInit(short Enable[,short SendMode[,short CycleTime[,short CanIdNum,short* pCanIdList]]);
parameter:
Enable: Whether to enable register table communication: 0 - Disabled, 1 - Enabled. SendMode: Sending method: 0 - Send upon receiving token (slave), 1 - Send periodically (master).
CycleTime: Periodic transmission time, in milliseconds. CanIdNum: Number of peer node IDs. pCanIdList: List of peer node IDs.
2) Add bit-type data to the register table SMCCanRegTableAddBit: short SMCCanRegTableAddBit(short CanId, short RegAddr, short RegNum, Dshort RegValue);
parameter:
CanId peer node number
RegAddr peer register address
RegNum: Number of peer registers, range [1, 32]
RegValue Default Value
3) Add character data to the register table SMCCanRegTableAddReg short SMCCanRegTableAddReg(short CanId, short RegAddr, short RegValue);
parameter:
CanId peer node number
RegAddr peer register address
RegValue Default Value
4) Add double-word data to register table SMCCanRegTableAddLong
short SMCCanRegTableAddLong(short CanId,short RegAddr,long RegValue);
parameter:
CanId peer node number
RegAddr peer register address
RegValue Default Value
5) Add floating-point data to the register table SMCCanRegTableAddFloat
short SMCCanRegTableAddFloat(short CanId,short RegAddr,float RegValue);
parameter:
CanId peer node number
RegAddr peer register address
RegValue Default Value
6) Add an end marker to the register table SMCCanRegTableAddEnd short SMCCanRegTableAddEnd(short CanId);
parameter:
CanId peer node number
7) Update the bit class data in the register table: `SMCCanRegTableSetBit short SMCCanRegTableSetBit(short CanId, short RegAddr, short RegNum, long RegValue);`
parameter:
CanId peer node number
RegAddr peer register address
RegNum: Number of peer registers, range [1, 32]
RegValue sets the value; each bit represents the value of a bit register.
8) Update the word class data in the register table SMCCanRegTableSetReg
short SMCCanRegTableSetReg(short CanId,short RegAddr,short RegValue);
parameter:
CanId peer node number
RegAddr peer register address
RegValue setting value
9) Update the double-word data in the register table: `SMCCanRegTableSetLong short SMCCanRegTableSetLong(short CanId, short RegAddr, long RegValue);`
parameter:
CanId peer node number
RegAddr peer register address
RegValue setting value
10) Update the floating-point data in the register table: `SMCCanRegTableSetFloat short SMCCanRegTableSetFloat(short CanId, short RegAddr, float RegValue);`
parameter:
CanId peer node number
RegAddr peer register address
RegValue setting value
III. Example of cascading three SMC304 motion controllers via CAN bus
1. Hardware setup for the example program
As shown in Figure 3.1, three SMC304 motion controllers are cascaded via a CAN bus. The CAN1 port of the motion controller with node number ID1 is connected to six CANopen bus motors and modules. (See the previous article: Applications of SMC304 Controllers and CANopen Bus Products)
The CAN bus DIP switch settings for the three SMC304 motion controllers are as follows:
The DIP switch for ID1 is set to: Off, Off, On, Off, Off, On. This means: CAN1 is used with the terminating resistor, CAN0 and CAN1 are used independently, and CAN0 is used with the terminating resistor.
The DIP switch for ID2 is: Off, Off, Off, On, On, Off. This means: CAN1 terminating resistor disabled; CAN0 and CAN1 shorted together as one interface; CAN0 terminating resistor disabled.
The DIP switch for ID3 is: Off, Off, Off, Off, Off, On. That is: CAN1 terminating resistor disabled, CAN0 and CAN1 used independently, CAN0 terminating resistor used.
2. Communication data of the routine
The ID2 motion controller is used as the master station, and the ID1 and ID3 controllers are used as slave stations.
D2 sends one character-type data to ID1 every 80 milliseconds; and sends one character-type data and one floating-point data to ID3.
After ID1 receives the token, it sends a character-type data to both ID2 and ID3.
After receiving the token, ID3 sends a character data to ID1; and sends a character data, a bit data (4 bits), and a floating-point data to ID2.
3. Function of the routine
The software for this experiment has the following functions:
Controllers ID1, ID2, and ID3 send an integer ranging from 0 to 11 to controllers ID2, ID3, and ID1 respectively, causing the indicator lights on their output ports OUT1 to OUT11 to flash in a running light pattern from left to right once every 0.2 seconds.
Controllers ID1, ID2, and ID3 send an integer ranging from 11 to 0 to controllers ID3, ID1, and ID2 respectively, causing the indicator lights on their output ports OUT10-OUT0 to flash in a running light pattern from right to left every 0.2 seconds. This is used to test the communication speed and reliability of the CAN bus token network for transmitting character data.
2) Every 0.2 seconds, controller ID2 combines an integer and a floating-point number into a single floating-point number and sends it to controller ID3 to control its motor to perform point-to-point movements. This is used to test the reliability of the CAN bus token network for transmitting floating-point data.
3) Every 0.2 seconds, controller ID3 sends controller ID2 a 4-bit bit data (ranging from 0 to 15 in ascending order) and a floating-point data (ranging from 1111.5678 to 8888.5678 in ascending order). Controllers ID1 and ID2 check the correctness of the received bit, word, and floating-point data.
4) Controller ID1 controls two CANopen stepper motors, one CANopen hybrid servo motor, two CANopen IO expansion modules, and one CANopen AD/DA module through CAN1 port.
4. Listing of the routine
Listing 1: ID2 program
auto: 'This machine is ID2, and is the master.
undim *
dim Cerr1,Cerr2,Ccheck
dim state1,state2
dim state3,state4,state
dim data0,data1,data2,data3
dim data0old,data1old
dim d0,d1,d2,d3
dim t1,t2,t
dim f1,f8
dim flag1,flag2
constCanID1=1 ' The node number of ID1 is 1
const CanID2=3 ' The node number of ID2 is 3
const CanID3=5 ' The node number of ID3 is 5
`setcan(1000, CanID2)` ' The baud rate of ID2 is 1000k.
call RegTableInit() ' Run the subroutine RegTableInit
flag1=0
flag2=0
state1=20000
state2=30011
state3=0
state4=-91111.567
data0=1
f1=1234.5678
f8=8888.5678
int_enable(1) 'Interrupt enable: On'
timer_start(0,20) 'Start timer 0
while true
Delay(200) 'Delays for 200 milliseconds'
if state1>=20011 then
state1=20000 'The base is set to 20000 simply to verify the accuracy of transmitting large amounts of data.'
else
state1 = state1 + 1 'state1 changes from small to large between 20000 and 20011, changing once every 200 milliseconds.
endif
If state2 <= 30000 then
state2=30011
else
state2 = state2 - 1 'state2 changes from large to small between 30011 and 30000, changing every 200 milliseconds.
endif
if state4>=8888.0 then
state4 = -7777.7777
state3=1
else
state3 = state3 + 1 'state3 changes from large to small between 1 and 16, changing once every 200 milliseconds.
state4 = state4 + 1111.12345 'state4 changes from small to large between -7777.777 and 8889.074.
endif
If state4>=0 then 'Merge state3 and state4 into a single floating-point number'
state = state4 + state3 * 10000
else
state = state4 - state3 * 10000
endif
SMCCANRegTableSetReg(CanID1,20,state2) ' Updates the sent data
SMCCANRegTableSetReg(CanID3,20,state1) SMCCanRegTableSetFloat(CanID3,26,state)
wend
end
ontimer0: ' This machine is ID2, and checks the status of ID1 and ID3 every 50 milliseconds.
timer_start(0, 50) ' Starts timer 0 with a timeout of 50 milliseconds.
d1=modbus_Reg(10) ' Read the local registers and check the instructions for controller ID1.
d2 = d1 - 20000 ' d2 increases from small to large between 0 and 11
If d2%2=0 then 'When d2=0, 2, 4, 6, 8, 10,
SMCWriteOutBit(d2+1,0) ' Lights up LEDs OUT1, OUT3, OUT5, OUT7, OUT9, and OUT11.
else 'When d2=1, 3, 5, 7, 9, 11,
SMCWriteOutBit(d2,1) ' Turns off LEDs OUT1, OUT3, OUT5, OUT7, OUT9, and OUT11.
endif
d1=modbus_Reg(30) ' Read the local registers and check the instructions for controller ID3.
d3 = d1 - 30000 ' d3 decreases from large to small between 11 and 0.
if d3%2=0 then ' When d3=10, 8, 6, 4, 2, 0,
SMCWriteOutBit(d3,1) ' Turns off LEDs OUT10, OUT8, OUT6, OUT4, OUT2, and OUT0.
else 'When d3 = 11, 9, 7, 5, 3, 1,
SMCWriteOutBit(d3-1,0) ' Lights up LEDs OUT10, OUT8, OUT6, OUT4, OUT2, and OUT0.
endif
data0 = MODBUS_BIT(30, 33)
if flag1=0 then
flag1=1 ' First read of ID3 bit class data
data0old=data0
else
If data0 <> data0old, then check the accuracy of data transmission based on ordered data.
if data0=data0old+1 or (data0=0 and data0old=15) then
else
Cerr1 = Cerr1 + 1 ' The bit class data transmitted for ID3 is incorrect, increment the count by 1.
print "error data = ",data0,data0old
endif
data0old=data0
endif
endif
data1=MODBUS_IEEE(36)
if flag2=0 then
flag2=1 ' First read of ID3 floating-point data
data1old=data1
else
If data1 <> data1old, then 'Check the accuracy of data transmission based on ordered data'.
if data1-(data1old+1110.997)<0.001 or (data1-f1<0.001 and data1-f8<0.001) then
else
Cerr2 = Cerr2 + 1 ' There is an error in the floating-point data transmitted for ID3, increment the count by 1.
print "error data = ",data1,data1old
endif
data1old=data1
endif
endif
Ccheck = Ccheck + 1
end
sub RegTableInit()
dim CanIdList(2) 'Defines a list of slave node numbers
CanIdList(0) = 1 'The first slave node number is 1'
CanIdList(1) = 5 'The second slave node number is 5'
SMCCANRegTableInit(1,1,80,2,CanIdList) 'Initializes the register table with a period of 80 milliseconds and a slave node count of 2.
SMCCANRegTableAddReg(CanID1,20,0) 'Add register data
SMCCANRegTableAddReg(CanID3,20,0) SMCCanRegTableAddFloat(CanID3,26,0)
SMCCANRegTableAddEnd(CanID1) 'End of register data flag'
end sub
Listing 2: ID3 Program
auto: 'This machine is ID3 and is a slave.
undim *
dim Cerr1,Cerr2,Ccheck
dim state1,state2
dim state3,state4
dim data0,data1,data2,data3
dim d0,d1,d2,d3
dim t1,t2,t
dim f1,f8
dim flag1,flag2
dim MaxData,MinData
const CanID1=1
const CanID2=3
const CanID3=5
MaxData=-1000
MinData=9999
flag1=0
flag2=0
state1=20000
state2=30011
state3=0
state4=1111.5678
data0=1
f1=1234.567
f8=8888.567
setcan(1000, CanID3)
call RegTableInit()
int_enable(1) 'Interrupt enable: On'
timer_start(0,20) 'Start the timer
SMCSetProfileUnit(0,900,6000,0.2,0.1,900) 'Sets the velocity curve parameters for axis 0.
SMCSetsprofile(0,0,0.5) 'Sets the parameters of segment S on axis 0.
while true
Delay(200)
if state1>=20011 then ' ……
state1=20000
else
state1 = state1 + 1
The `endif` directive is the same as the ID2 procedure.
If state2 <= 30000 then
state2=30011
else
state2 = state2 - 1
endif ' ……
If state3>=15 then
state3=0
else
state3 = state3 + 1 'state3 changes from small to large between 0 and 15, changing once every 200 milliseconds.
endif
if state4>=8888.5678 then
state4=1111.5678
else
state4 = state4 + 1111 'state4 changes from small to large between 1111.5678 and 8888.5678.
endif
SMCCANRegTableSetReg(CanID1,30,state1) ' Updates the sent data
SMCCANRegTableSetReg(CanID2,30,state2) SMCCanRegTableSetBit(CanID2,30,4,state3) SMCCanRegTableSetFloat(CanID2,36,state4)
data1=MODBUS_IEEE(26)
if data1>= 0 then 'Split data1 into 2 numbers
data0 = int(data1/10000) ' data0 is an integer between 1 and 16
data2 = data1 - data0 * 10000 ' data2 is a floating-point number between -7777.777 and 8889.074
else
data0 = -1 * int(data1/10000) - 1
data2 = data1 + data0 * 10000
endif
If data0=4 or data0=12 then 'Move the points based on data0 and data2'
SMCPMoveUnit(0,data2,0)
endif
wend
end
ontimer0: ' This machine is ID3, and checks the status of ID1 and ID2 every 50 milliseconds.
timer_start(0,50)
d1=modbus_Reg(20) ' Read the local registers and check the instructions for controller ID2.
d2=d1-20000
If d2%2=0 then ' Same as ID2 procedure'
SMCWriteOutBit(d2+1,0)
else
SMCWriteOutBit(d2,1)
endif
d1=modbus_Reg(10) ' Read the local registers and check the instructions for controller ID1.
d3=d1-30000
If d3%2=0 then ' Same as ID2 procedure'
SMCWriteOutBit(d3,1)
else
SMCWriteOutBit(d3-1,0)
endif
end
sub RegTableInit()
SMCCanRegTableInit(1,0,0) 'Initialize the register table
SMCCanRegTableAddReg(CanID1,30,0) 'Add register data
SMCCanRegTableAddReg(CanID2,30,0)
SMCCanRegTableAddBit(CanID2,30,4,0) 'Bit class data of length 4 bits
SMCCanRegTableAddFloat(CanID2,36,0)
SMCCanRegTableAddEnd(CanID2) 'End of register data flag'
end sub
Listing 3: Program for ID1
auto: ' This machine is ID1, and is a slave.
undim *
dim a,b,flag1,flag2,Cerr1,Cerr2,Ccheck
dim EMoutV0,EMoutV1,EMinV0
dim state1,state2
dim d1,d2,d3,d2old,d3old
dim t1,t2,t,Tmax
Tmax=0
flag1=0
flag2=0
const EM1out0=12
const EM1out8=20
const EM1out5=18
const EM1out13=25
const EM1in0=16
const EM1in8=24
const EM2out1=29
const EM2out9=37
const EM2out6=34
const EM2out14=42
const EM2in1=33
const EM2in9=41
const CanID1=1
const CanID2=3
const CanID3=5
setcan(1000, CanID1)
call RegTableInit()
a=off
b=off
EMoutV0=0
EMoutV1=0
EMinV0=0
state1=20000
state2=30011
int_enable(1) 'Interrupt enable: On'
timer_start(0,50) 'Start timer 0
timer_start(1,60) 'Start timer 1 and control the I/O module'
run 1,canmotor 'Controls CAN bus motors'
count=0
while true
Delay(200)
if state1>20011 then
state1=20000
else
state1 = state1 + 1
endif
if state2 < 30000 then
state2=30011
else
state2 = state2 - 1
endif
SMCCANRegTableSetReg(CanID2,10,state1) ' Updates the sent data
SMCCANRegTableSetReg(CanID3,10,state2)
wend
end
canmotor: 'Subtask for controlling CANopen motors'
... (Program details omitted; see the previous article for more information: Application of SMC304 Controller and CANopen Bus Products)
end
ontimer1: 'AD/DA module control'
... (Program omitted)
end
EM32IOControl: 'Subtask for controlling the I/O module'
... (Program omitted)
end
ontimer0: ' This machine is ID1, and checks the status of ID2 and ID3 every 20+ milliseconds.
t1=ticks
d1=modbus_Reg(30) ' Read the local registers and check the instructions for controller ID3.
d2=d1-20000
if flag1=0 then
flag1=1 ' First time
d2old=d2
if d2%2=0 then
SMCWriteOutBit(d2+1,0)
else
SMCWriteOutBit(d2,1)
endif
else
if d2<>d2old then
if d2=d2old+1 or (d2=0 and d2old=11) then
if d2%2=0 then
SMCWriteOutBit(d2+1,0)
else
SMCWriteOutBit(d2,1)
endif
else
Cerr1 = Cerr1 + 1 ' The data transmitted by ID3 is incorrect, increment the count by 1.
print "error data = ",d2,d2old
endif
d2old=d2
endif
endif
d1=modbus_Reg(20) ' Read the local registers and check the instructions for controller ID2.
d3=d1-30000
if flag2=0 then
flag2=1 ' First time
d3old=d3
if d3%2=0 then
SMCWriteOutBit(d3,1)
else
SMCWriteOutBit(d3-1,0)
endif
else
if d3<>d3old then
if d3=d3old-1 or (d3=11 and d3old=0) then
if d3%2=0 then
SMCWriteOutBit(d3,1)
else
SMCWriteOutBit(d3-1,0)
endif
else
Cerr2 = Cerr2 + 1 ' The data transmitted by ID2 is incorrect, increment the count by 1.
print "error data = ",d3,d3old
endif
d3old=d3
endif
endif
Ccheck = Ccheck + 1
timer_start(0, 20)
t2=ticks
t=t2-t1 ' Measure the runtime of ontimer0
if t>Tmax then
Tmax=t
print "max time = ",t ' Outputs the maximum running time
endif
end
sub RegTableInit()
SMCCanRegTableInit(1,0,0) 'Initialize register table SMCCanRegTableAddReg(CanID2,10,0) 'Add number of registers
SMCCanRegTableAddReg(CanID3,10,0) SMCCanRegTableAddEnd(CanID2) 'End of register data flag
end sub
5. Experimental results of the routine
Three SMC304 motion controllers are cascaded via a CAN bus token network to achieve stable and reliable data exchange. The program was tested for dozens of hours without a single communication error.
The average communication time for transmitting a single character of data is less than 5 milliseconds. Because controller ID1 has a heavy workload, the average completion time of its interrupt task for updating timer0, which is responsible for transmitting data, is around 35 milliseconds, but the longest is nearly 70 milliseconds. Therefore, master station ID2 sets the data communication cycle to 80 milliseconds.
It should be noted that one scenario is possible: when querying the local register, the i-th data was received in the previous cycle, and the (i+1)-th data was received in the current cycle.
If these two data points are related, such as the i-th data point being the axis number and the (i+1)-th data point being the movement distance, and the data transmitted in the j-th cycle and the (j+1)-th cycle are different, an error will occur. Therefore, to avoid this situation, these two related data points can be merged into one data point for transmission.
IV. Conclusion
The SMC304 motion controller uses CAN bus token network cascading, offering fast, stable, and reliable communication. It fully utilizes the SMC304's trajectory control capabilities, allowing for a wider range of AC servo motors to be used. The reduced number of bus-type motors controlled by the controller lowers the programming complexity of the bus control system. Therefore, this networking method is highly suitable for small production lines.
In summary, by using the SMC304 motion controller and CANopen bus stepper motors, hybrid servo motors, and expansion modules, Leadshine's advantages can be fully utilized, significantly improving the cost-effectiveness of the motion control system.
V. References
[1] Zhao Cheng, Zhang Kai. Design of Real-time Token Ring Based on CAN Bus. Microcomputer Applications, No. 9, 2013.
[2] Shenzhen Leadshine Control Technology Co., Ltd. Leadshine SMC304-BAS Motion Controller User Manual. 2019
[3] Shenzhen Leadshine Control Technology Co., Ltd. Leadshine SMC Basic Studio User Manual. 2019
Disclaimer: This article is provided by the company. If it involves copyright or confidentiality issues, please contact us promptly for deletion (QQ: 2737591964 ) . We apologize for any inconvenience.