AB&T
/
EasyCAT_LAB_very_simple
EasyCAT LAB - EtherCAT master very simple example
- This repository contains a very basic example for the EasyCAT LAB , a complete educational and experimental EtherCAT® system, composed of one master and two slaves.
- The EasyCAT LAB is provided as a kit by AB&T Tecnologie Informatiche, to allow everybody to have an educational EtherCAT® system up and running in a matter of minutes.
- It uses the SOEM (Simple Open EtherCAT® Master) library by rt-labs, that has been ported in the ecosystem by AB&T Tecnologie Informatiche.
- The slaves are based on the EasyCAT SHIELD and the Arduino UNO.
Note
- This example uses two LAB 2 slaves.
Note
- In this example, to keep things as simple as possible, only two bytes of data are exchanged between the slaves and the TFT display is not used .
Diff: main.cpp
- Revision:
- 0:bc829777f1ea
- Child:
- 1:971b4897a4c5
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Tue Jul 09 16:25:27 2019 +0000 @@ -0,0 +1,292 @@ +//******************************************************************************************** +// * +// This software is distributed as an example, "AS IS", in the hope that it could * +// be useful, WITHOUT ANY WARRANTY of any kind, express or implied, included, but * +// not limited, to the warranties of merchantability, fitness for a particular * +// purpose, and non infringiment. In no event shall the authors be liable for any * +// claim, damages or other liability, arising from, or in connection with this software. * +// * +//******************************************************************************************** + + +// The AB&T EasyCAT LAB is a complete experimental EtherCAT® system, composed by +// one master and two slaves. +// The EasyCAT LAB software is provided free of charge and its pourpose is to allow +// makers and educational institutes to experiment with the EtherCAT® protocol. +// +// The EasyCAT LAB is developed by "AB&T Tecnologie Informatiche" Via dell'About 2A Ivrea Italy. +// www.bausano.net +// www.easycatshield.com +// +// The EasyCAT LAB uses the SOEM library by rt:labs +// https://rt-labs.com/products/soem-ethercat-master-stack/ +// +// EtherCAT® is a registered trademark and patented technology, licensed by Beckhoff Automation GmbH. +// www.beckhoff.com +// www.ethercat.org + + +#define ETH_TXBUFNB 16 +#define ETH_RXBUFNB 16 + +#include "mbed.h" + +#ifndef __align +#define __align MBED_ALIGN +#endif + +#include "config.h" +#include "soem_start.h" + +#define CYCLE_TIME 1000 // master cycle time in uS + // 1000 = 1mS + + +#define SysMilliS() (uint32_t)Kernel::get_ms_count() + +Serial pc(USBTX,USBRX,115200); // set the debug serial line speed to 115200 + + + +//---- local functions --------------------------------------------------------- + +void Application(); +void BlinkLedForever(); + +//------------------------------------------------------------------------------ + +Ticker SampleTicker; +Thread thread; + +DigitalOut Test_1(D1); // debug test points +DigitalOut Test_2(D2); // +DigitalOut Test_3(D3); // +DigitalOut Test_4(D4); // + +DigitalOut LED_RED(LED3); + + +//------------------------------------------------------------------------------ + +int ExpectWorkCounter; +int WorkCounter; +int WorkCounterSafe; +bool NetworkError; +bool NetworkErrorSafe; + +#define DATA_EXCHANGE_FLAG (1UL << 0) +#define APPLICATION_FLAG (1UL << 1) + +EventFlags event_flags; + +Mutex IO_data; + + +//---- data exchange thread ---------------------------------------------------- + +void ExchangeMaster() +{ + while (true) + { + event_flags.wait_any(DATA_EXCHANGE_FLAG); // the thread waits for the synchronization flag + + //Test_1 = 1; + + IO_data.lock(); // Ethercat data exchange + ec_send_processdata(); // + WorkCounter = ec_receive_processdata(EC_TIMEOUTRET); + + if (WorkCounter != ExpectWorkCounter) + NetworkError = true; + else + NetworkError = false; + + IO_data.unlock(); // + event_flags.set(APPLICATION_FLAG); // synchronize the application + + //Test_1 = 0; + } +} + + +//----- thicker generated sample time ------------------------------------------ + +void SampleIsr() // set the event that starts +{ // the data exchange + event_flags.set(DATA_EXCHANGE_FLAG); // +} // + + +//****** initialization ******************************************************** + +int main() +{ + int i; + + printf("Start \n"); + + Test_1 = 0; + Test_2 = 0; + Test_3 = 0; + Test_4 = 0; + + NetworkError = false; + + if (ec_init(NULL)) // init SOEM + { + printf("ec_init succeeded.\n"); + printf("Scanning the network\n"); + + if (network_scanning()) + { + if (network_configuration()) // check network configuration + { + ec_config_map(&IOmap); // map the I/O + MapLocalStructures(); + + printf("\nSlaves mapped, state to SAFE_OP.\n"); + // wait for all slaves to reach SAFE_OP state + ec_statecheck(0, EC_STATE_SAFE_OP, EC_TIMEOUTSTATE); + + printf("Request operational state for all slaves\n"); + ec_slave[0].state = EC_STATE_OPERATIONAL; + + ec_send_processdata(); // send one valid process data to make outputs in slaves happy + ExpectWorkCounter = ec_receive_processdata(EC_TIMEOUTRET); + + ec_writestate(0); // request OP state for all slaves + + // wait for all slaves to reach OP state + ec_statecheck(0, EC_STATE_OPERATIONAL, EC_TIMEOUTSTATE); + if (ec_slave[0].state == EC_STATE_OPERATIONAL ) + { + printf("Operational state reached for all slaves.\n"); + } + else + { + printf("Not all slaves reached operational state.\n"); + ec_readstate(); + for(i = 1; i<=ec_slavecount ; i++) + { + if(ec_slave[i].state != EC_STATE_OPERATIONAL) + { + printf("Slave %d State=0x%04x StatusCode=0x%04x\n", + i, ec_slave[i].state, ec_slave[i].ALstatuscode); + } + } + + printf("Not all slaves reached operational state!\n"); + void BlinkLedForever(); + } + + + thread.start(ExchangeMaster); + thread.set_priority(osPriorityRealtime); + + SampleTicker.attach_us(&SampleIsr, CYCLE_TIME); + + Application(); + } + + else + { + printf("Mismatch of network units!\n"); + BlinkLedForever(); + } + } + + else + { + printf("No slaves found!\n"); + BlinkLedForever(); + } + } + else + { + printf("Ethernet interface init failed!"); + BlinkLedForever(); + } +} + + +//****** user master application ********************************************** + +void Application() +{ + + while(1) + { + event_flags.wait_any(APPLICATION_FLAG); // the application waits for the synchronization flag + + //Test_2 = 1; + + IO_data.lock(); // copy the Ethercat data to a safe buffer + memcpy(&IOmapSafe[0], &IOmap[0], IO_MAP_SIZE); // + // + if (NetworkError) // + { // + NetworkErrorSafe = NetworkError; // + WorkCounterSafe = WorkCounter; // + } // + IO_data.unlock(); // + + if (NetworkErrorSafe) + { + printf("Network error!\n"); + + if(WorkCounterSafe >= 0) + { + printf("Expected working counter %d\n", ExpectWorkCounter); + printf("Actual working counter %d\n", WorkCounterSafe); + } + else + { + printf("Timeout\n"); + } + + printf("Please fix the error and press the reset button \n"); + + SampleTicker.detach(); // stop the sample interrupt + BlinkLedForever(); // and loop for ever + } + + + //----- slaves data management ----------- + + + out_LAB_2_1->Segments = in_LAB_2_2->Buttons; // send to the slave LAB_2_1 the buttons status + // from the slave LAB_2_2 + + + out_LAB_2_2->Segments = in_LAB_2_1->Buttons; // send to the slave LAB_2_2 the buttons status + // from the slave LAB_2_1 + + + //---------------------------------------- + + + + IO_data.lock(); // copy the IO data from the safe area + memcpy(&IOmap[0], &IOmapSafe[0], IO_MAP_SIZE); // to the EtherCAT buffer + IO_data.unlock(); // + + //Test_2 = 0; + } +} + +//****************************************************************************** + + +void BlinkLedForever() // blink the red led forever to signal + // an unrecoverable error condition + + // fix the error and press the reset button +{ + while(1) + { + LED_RED = !LED_RED; + wait_ms(100); + } +} + +