[etherlab-users] Beckhoff EL6001/EL6021 Issues
Richard Hacker
ha at igh.de
Sat May 24 14:32:15 CEST 2014
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
> http://lists.etherlab.org/mailman/listinfo/etherlab-users
>
Mit freundlichem Gruß
Richard Hacker
--
------------------------------------------------------------------------
Richard Hacker M.Sc.
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
------------------------------------------------------------------------
More information about the Etherlab-users
mailing list