EasyCAT LAB - EtherCAT master very simple example

Dependencies:   SOEM

  • 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.

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 .

main.cpp

Committer:
EasyCAT
Date:
11 months ago
Revision:
2:368e7d4d8171
Parent:
1:971b4897a4c5

File content as of revision 2:368e7d4d8171:

//********************************************************************************************    
//                                                                                           *
// 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()                                      

UnbufferedSerial 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_1->Segments = in_LAB_2->Buttons;                    // send to the slave LAB_2_1 the buttons status
                                                                    // from the slave LAB_2_2    
                                                                    
                                                                                  
        out_LAB_2->Segments = in_LAB_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;
        ThisThread::sleep_for(100ms);   
    }
}