[etherlab-users] Beckhoff EL6001/EL6021 Issues
Derrill Vezina
dvezina at caron-eng.com
Tue May 27 17:24:40 CEST 2014
Richard,
Thank you for the reply. I have tried what you suggested with the wire bridge just talking to one EL6001 with a EK1100 bus coupler. I pulled everything out of my existing application that is currently running 10+ slaves and made it a stand alone application.
I attached my standalone application for usage of the EK1100 (position 0) and the EL6001 (position 1) with a 1mS loop timer. After a successful initialization, it starts sending data immediately. Its quick and dirty.
The outcome is the same, I am initializing successfully, and receiving a transmit accepted, but no data is going out the port and no lights flashing, which means there is no data to be received.
The only thing that doesn’t really match with my code compared to your initialization description is the out length byte[1] of TxPDO. The out length and in length are the second byte of the SW and CW, which is what I mask / set to send data (CW) and read data (SW). Do you use a different sync structure / pdo structure than I do?
Thank you again for the support.
Derrill Vezina | Electrical Engineer
Caron Engineering Inc.
Direct : 207.641.6839
Cell : 207.251.9072
www.caron-eng.com<http://www.caron-eng.com>
On May 24, 2014, at 8:32 AM, Richard Hacker <ha at igh.de<mailto:ha at igh.de>> wrote:
Firstly, I only have experience with EL6022, but the EL6001 is not much different.
Start with small steps:
Connect TxD to RxD on the slave with a wire bridge to create a loopback.
Initialization:
PDO mapping:
RxPdo = 0x1604 (CW and OutData: 24 bytes) to SyncManager 2
TxPdo = 0x1a04 (SW and InData: 24 bytes) to SyncManager 3
SW is byte[0] of TxPdo
CW is byte[0] of RxPdo
OutLength is byte[1] of RxPdo
OutData = byte[2..24] of RxPdo
SDO settings:
0x8000:0x01 = 0 (disable RTS/CTS)
0x8000:0x05 = 0 (disable transfer rate optimization)
0x8000:0x11 = 10 (115200 baud)
0x8000:0x15 = 3 (8N1)
CW.InitRequest = 1
wait for SW.InitAccepted == 1
CW.InitRequest = 0
CW.OutLength = 10
Data[0..9] = random
Cyclic:
CW.TransmitRequest = !SW.TransmitAccepted
CW.ReceiveAccepted = SW.ReceiveRequest
sleep 1ms
By setting TransmitRequest to be inverse of TransmitAccepted, the slave will continuously transmit 10 bytes which are received again due to the loopback, causing TxD and RxD LED's to flicker. If they don't, there is something wrong in your program! Try to get this working first.
The above program should be a 50-liner (or so) for the actual coding. You could implement this using state machines, but for a short test program, I would attempt without first.
- Richard
On 05/23/2014 03:01 PM, Derrill Vezina wrote:
I have 3 state machines in my code, initialization, write, and read. The
write and read state machines cannot be incremented until the
initialization state machine has completed.
Everything I have done seems to match your data flow, the only
difference was I was setting the 0x407x registers for the SDO
configuration (the Beckhoff docs said from hardware version 03 so I
wanted it to be compatible). I changed my SDO writes to the 8000:xx
registers, but this did not change the data not pushing out the port. I
am running the EL6021 in half duplex mode so I have tx+ tied to rx+ and
tx- tied to tx-. Since I am seeing the issue with the EL6021 and the
EL6001, I am just trying to get the EL6001 working first since I have
the other side of the transmission line hooked up to PC.
My system is setup through a configuration file which is parsed on
startup and the system adapts to what was in the contents of the file. I
currently have 10 or so Beckhoff cards which are mostly I/O modules.
Therefore, the SDO registers are only set on startup and do not need to
have their own state machine in realtime since they can’t really change
dynamically. I write all SDO registers before I configure the PDOs / domain.
Here’s how I am writing my SDO registers for the EL6001 and EL6021:
// do all of the write requests....
// the write value will change with respect to the data set in the
configuration file
//
// send xon xoff tx
data[0] = ecat.device[i].EL60xx_xon_xoff_tx ? 1 : 0;
*if* (*ecrt_master_sdo_download*(ecat.master, i, 0x8000, 0x02, data, 1,
&abort_code) < 0)
LOGMSG(/LOG_WARNING/) << "Failed to upload xon xoff tx SDO with code "<<
abort_code;
// check xon xoff rx
data[0] = ecat.device[i].EL60xx_xon_xoff_rx ? 1 : 0;
*if* (*ecrt_master_sdo_download*(ecat.master, i, 0x8000, 0x03, data, 1,
&abort_code) < 0)
LOGMSG(/LOG_WARNING/) << "Failed to upload xon xoff rx SDO with code "<<
abort_code;
// check the baud rate
*switch* (ecat.device[i].EL60xx_baud_rate){
case 2400: data[0] = EL60XX_BAUD_2400; *break*;
*case* 4800: data[0] = EL60XX_BAUD_4800; *break*;
*case* 9600: data[0] = EL60XX_BAUD_9600; *break*;
*default*:
*case* 19200: data[0] = EL60XX_BAUD_19200; *break*;
*case* 38400: data[0] = EL60XX_BAUD_38400; *break*;
*case* 57600: data[0] = EL60XX_BAUD_57600; *break*;
*case* 115200: data[0] = EL60XX_BAUD_115200; *break*;
}
// upload the baud rate
*if* (*ecrt_master_sdo_download*(ecat.master, i, 0x8000, 0x11, data, 1,
&abort_code) < 0)
LOGMSG(/LOG_INFO/) << "Failed to upload baud rate with code "<< abort_code;
// check the data frame
*if* (ecat.device[i].EL60xx_data_bits == 7 &&
ecat.device[i].EL60xx_stop_bits == 1 && ecat.device[i].EL60xx_parity == 1)
data[0] = EL60XX_DATA_7E1;
*else* *if* (ecat.device[i].EL60xx_data_bits == 7 &&
ecat.device[i].EL60xx_stop_bits == 1 && ecat.device[i].EL60xx_parity == 2)
data[0] = EL60XX_DATA_7O1;
*else* *if* (ecat.device[i].EL60xx_data_bits == 8 &&
ecat.device[i].EL60xx_stop_bits == 1 && ecat.device[i].EL60xx_parity == 0)
data[0] = EL60XX_DATA_8N1;
*else* *if* (ecat.device[i].EL60xx_data_bits == 8 &&
ecat.device[i].EL60xx_stop_bits == 1 && ecat.device[i].EL60xx_parity == 1)
data[0] = EL60XX_DATA_8E1;
*else* *if* (ecat.device[i].EL60xx_data_bits == 8 &&
ecat.device[i].EL60xx_stop_bits == 1 && ecat.device[i].EL60xx_parity == 2)
data[0] = EL60XX_DATA_8O1;
*else* *if* (ecat.device[i].EL60xx_data_bits == 7 &&
ecat.device[i].EL60xx_stop_bits == 2 && ecat.device[i].EL60xx_parity == 2)
data[0] = EL60XX_DATA_7O2;
*else* *if* (ecat.device[i].EL60xx_data_bits == 8 &&
ecat.device[i].EL60xx_stop_bits == 2 && ecat.device[i].EL60xx_parity == 0)
data[0] = EL60XX_DATA_8N2;
*else* *if* (ecat.device[i].EL60xx_data_bits == 8 &&
ecat.device[i].EL60xx_stop_bits == 2 && ecat.device[i].EL60xx_parity == 1)
data[0] = EL60XX_DATA_8E2;
*else* *if* (ecat.device[i].EL60xx_data_bits == 8 &&
ecat.device[i].EL60xx_stop_bits == 2 && ecat.device[i].EL60xx_parity == 2)
data[0] = EL60XX_DATA_8O2;
*else*
data[0] = EL60XX_DATA_7E2;
// upload the data frame
*if* (*ecrt_master_sdo_download*(ecat.master, i, 0x8000, 0x15, data, 1,
&abort_code) < 0)
LOGMSG(/LOG_INFO/) << "Failed to upload data frame with code "<< abort_code;
// check send fifo data continuous
data[0] = ecat.device[i].EL60xx_send_fifo_continuous ? 1 : 0;
if (*ecrt_master_sdo_download*(ecat.master, i, 0x8000, 0x04, data, 1,
&abort_code) < 0)
LOGMSG(/LOG_INFO/) << "Failed to upload send fifo cont. SDO
with code "<< abort_code;
// check send transfer rate opt.
data[0] = ecat.device[i].EL60xx_transfer_rate_opt ? 1 : 0;
*if* (*ecrt_master_sdo_download*(ecat.master, i, 0x8000, 0x05, data, 1,
&abort_code) < 0)
LOGMSG(/LOG_INFO/) << "Failed to upload transfer rate opt. SDO with code
"<< abort_code;
// check the device type
*if* (ecat.device[i].dev_type == /DEV_EL6021/){
// send duplex
data[0] = ecat.device[i].EL6021_duplex ? 1 : 0;
*if* (*ecrt_master_sdo_download*(ecat.master, i, 0x8000, 0x06, data, 1,
&abort_code) < 0)
LOGMSG(/LOG_INFO/) << "Failed to upload duplex type SDO with code "<<
abort_code;
// check point to point communications
data[0] = ecat.device[i].EL6021_point_to_point ? 1 : 0;
*if* (*ecrt_master_sdo_download*(ecat.master, i, 0x8000, 0x07, data, 1,
&abort_code) < 0)
LOGMSG(/LOG_INFO/) << "Failed to upload point to point SDO with code "<<
abort_code;
}
*else* {
// check send rts cts
data[0] = ecat.device[i].EL6001_rts_cts_enable ? 1 : 0;
*if* (*ecrt_master_sdo_download*(ecat.master, i, 0x8000, 0x01, data, 1,
&abort_code) < 0)
LOGMSG(/LOG_INFO/) << "Failed to upload rts cts enable SDO with code "<<
abort_code;
}
Here is my initialization sm which finishes successfully:
// check the state of the initialization
*if* (ecat.device[device].EL60xx_init_status == /EL6021_Init_Terminal/){
// read the control register first and set initialization request bit to 1
*int* control_byte = EC_READ_U8(ecat.domain_pd +
ecat.device[device].EL60xx_control_offset);
control_byte |= EL60XX_CTRL_INIT_REQUEST;
EC_WRITE_U8(ecat.domain_pd + ecat.device[device].EL60xx_control_offset,
control_byte);
// wait for verification that the initialization succeed successfully
ecat.device[device].EL60xx_init_status = /EL6021_Init_Accepted/;
}
*else**if* (ecat.device[device].EL60xx_init_status ==
/EL6021_Init_Accepted/){
// read the status register to see if the device accepted the request
uint16_t status = EC_READ_U16(ecat.domain_pd +
ecat.device[device].EL60xx_status_offset);
if (status & EL60XX_STAT_INIT_ACCEPTED){
// clear the init request bit...
*int* control_byte = EC_READ_U8(ecat.domain_pd +
ecat.device[device].EL60xx_control_offset);
control_byte &= ~EL60XX_CTRL_INIT_REQUEST;
EC_WRITE_U8(ecat.domain_pd + ecat.device[device].EL60xx_control_offset,
control_byte);
// wait for the transmission success
ecat.device[device].EL60xx_init_status = /EL6021_Init_Verified/;
}
*else* {
// waiting for initialization accepted...
*if* (ecat.device[device].EL60xx_init_print){
LOGMSG(/LOG_INFO/) << "Still waiting for verification of transmission on
EL60xx";
ecat.device[device].EL60xx_init_print = *false*;
}
}
}
*else**if* (ecat.device[device].EL60xx_init_status ==
/EL6021_Init_Verified/) {
// check the status bit and wait for terminal to set the initialization
accepted bit to 0
uint16_t status = EC_READ_U16(ecat.domain_pd +
ecat.device[device].EL60xx_status_offset);
*if* (!(status & EL60XX_STAT_INIT_ACCEPTED)){
// everything is up and running!
ecat.device[device].EL60xx_init_status = /EL6021_Terminal_Ready/;
// notify the user
LOGMSG(/LOG_INFO/) << "EL60xx device read / write terminal ready for data";
}
}
My write state sm to be working correctly as well since when I set the
transmit request bit after filling the data bytes, the terminal sets the
transmit request accepted bit successfully, I am just not seeing data
coming out the port. This is happening with both the EL6021 and the EL6001.
This is how my write sm works right now (I just created a temporary
array of 8 bytes and filled it with random data, TEST_SIZE = 8):
// get the status used for write and write sm
uint16_t status = EC_READ_U16(ecat.domain_pd +
ecat.device[device].EL60xx_status_offset);
// check the write state
*if*(ecat.device[device].EL60xx_send_status== /EL6021_Send_Idle/){
// map the data to the output registers
*for* (*int* i=0;i<TEST_SIZE;i++)
EC_WRITE_U8(ecat.domain_pd + ecat.device[device].EL60xx_out_offset[i],
data[i]);
// set the second byte of the control register to be the size of the
output size
// mask with 255...
uint16_tcontrol_byte = (TEST_SIZE & 255) << 8;// bit shift over by 8 and
mask out the first byte
control_byte |= EL60XX_CTRL_TRANSMIT_REQUEST;
// set the transmit request bit
EC_WRITE_U8(ecat.domain_pd + ecat.device[device].EL60xx_control_offset,
control_byte);
// set next step in the transaction process
ecat.device[device].EL60xx_send_status= /EL6021_Send_Request/;
}
*else**if*(ecat.device[device].EL60xx_send_status== /EL6021_Send_Request/){
// check the status bit for successful transition...
*if* (status & EL60XX_STAT_TRANSMIT_ACCEPTED){
// transmit accepted and bytes sent to transmission FIFO
LOGMSG(/LOG_INFO/) << "Data transmission from EL6021 success with status
"<< status;
// set the status back to idle
ecat.device[device].EL60xx_send_status= /EL6021_Send_Idle/;
}
*else* {
// check for additional errors…
…
…
}
}
The transmit accepted status bit is set high, so my assumption is that
the terminal is receiving the data (my log prints “Data transmission
from EL6021 success with status ” every time through).
_______________________________________________
etherlab-users mailing list
etherlab-users at etherlab.org<mailto:etherlab-users at etherlab.org>
http://lists.etherlab.org/mailman/listinfo/etherlab-users
Mit freundlichem Gruß
Richard Hacker
--
------------------------------------------------------------------------
Richard Hacker M.Sc.
richard.hacker at igh-essen.com<mailto:richard.hacker at igh-essen.com>
Tel.: +49 201 / 36014-16
Ingenieurgemeinschaft IgH
Gesellschaft für Ingenieurleistungen mbH
Heinz-Bäcker-Str. 34
D-45356 Essen
Amtsgericht Essen HRB 11500
USt-Id.-Nr.: DE 174 626 722
Geschäftsführung:
- Dr.-Ing. T. Finke,
- Dr.-Ing. W. Hagemeister
Tel.: +49 201 / 360-14-0
http://www.igh-essen.com
------------------------------------------------------------------------
_______________________________________________
etherlab-users mailing list
etherlab-users at etherlab.org
http://lists.etherlab.org/mailman/listinfo/etherlab-users
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.etherlab.org/pipermail/etherlab-users/attachments/20140527/c6963679/attachment-0004.htm>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: EL6001.cpp
Type: application/octet-stream
Size: 28360 bytes
Desc: EL6001.cpp
URL: <http://lists.etherlab.org/pipermail/etherlab-users/attachments/20140527/c6963679/attachment-0005.obj>
More information about the Etherlab-users
mailing list