EasyCAT LAB - EtherCAT master simple example

Dependencies:   SOEM SPI_TFT_ILI9341 TFT_fonts

  • This repository contains a simple 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 only two bytes of data are exchanged between the slaves and are also visualized on the TFT display.
Revision:
0:13be39911caf
Child:
1:385bdd2b4cd6
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Mon Jul 08 17:44:47 2019 +0000
@@ -0,0 +1,522 @@
+//********************************************************************************************    
+//                                                                                           *
+// 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 "SPI_TFT_ILI9341.h"
+#include "Arial12x12.h"
+#include "Arial24x23.h"
+#include "Arial28x28.h"
+#include "font_big.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
+
+
+//---- TFT with resistive touchscreen pins -------------------------------------
+
+// the display used is the SeeedStudio 2.8 inch TFT v2.0
+// http://wiki.seeedstudio.com/2.8inch_TFT_Touch_Shield_v2.0/ 
+
+#define PIN_YP          A3                          // resistive touchscreen
+#define PIN_YM          A1                          //
+#define PIN_XM          A2                          //
+#define PIN_XP          A0                          //
+
+#define PIN_MOSI        D11                         // TFT display SPI
+#define PIN_MISO        D12                         //
+#define PIN_SCLK        D13                         //
+#define PIN_CS_TFT      D5                          //
+#define PIN_DC_TFT      D6                          //
+
+
+
+//---- visualization parameters ------------------------------------------------
+
+#define BUTTONS_1_X 80
+#define BUTTONS_1_Y 60
+
+#define BUTTONS_2_X 80
+#define BUTTONS_2_Y 180 
+ 
+ 
+#define BUTTONS_1_WIDTH 26
+#define BUTTONS_1_R 3
+#define BUTTONS_1_STEP 60 
+
+#define BUTTONS_2_WIDTH     BUTTONS_1_WIDTH 
+#define BUTTONS_2_R         BUTTONS_1_R
+#define BUTTONS_2_STEP      BUTTONS_1_STEP 
+
+
+//---- local functions ---------------------------------------------------------
+
+void DrawBanner();
+void DrawSlaveFixedParts();
+void DrawButtons_1_Value(uint8_t Value);
+void DrawButtons_2_Value(uint8_t Value);
+
+void Application();   
+
+
+//---- global variables --------------------------------------------------------
+
+
+bool FirstRound;
+
+//------------------------------------------------------------------------------
+
+SPI_TFT_ILI9341 TFT(PIN_MOSI, PIN_MISO, PIN_SCLK, PIN_CS_TFT, NC, PIN_DC_TFT);
+
+Ticker SampleTicker;
+Thread thread;
+
+DigitalOut Test_1(D1);          // debug test points
+DigitalOut Test_2(D2);          //
+DigitalOut Test_3(D3);          //
+DigitalOut Test_4(D4);          //
+
+
+//------------------------------------------------------------------------------
+
+uint8_t Buttons_1; 
+uint8_t PrevButtons_1;
+uint8_t Segments_1;
+uint8_t PrevSegments_1;
+
+uint8_t Buttons_2; 
+uint8_t PrevButtons_2;
+uint8_t Segments_2;
+uint8_t PrevSegments_2;
+   
+   
+//------------------------------------------------------------------------------   
+
+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;      
+  
+    TFT.background(Black);                                          // init TFT  
+    TFT.cls();                                                      //
+    TFT.set_orientation(3);                                         // 
+
+    DrawBanner();     
+        
+    NetworkError = false;  
+      
+    if (ec_init(NULL))                                              // init SOEM
+    {
+        printf("ec_init succeeded.\n");     
+        printf("Scanning the network\n");
+
+        TFT.cls();  
+                                                            
+        TFT.set_font((unsigned char*) Arial12x12);
+        TFT.foreground(Green);
+        TFT.locate(0, 0);
+        
+        TFT.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);
+                        }
+                    }
+                    
+                    TFT.foreground(Red);                                                     
+                    TFT.locate(0, 0);      
+                    TFT.printf("Not all slaves reached operational state!");                           
+                    while(1){}  
+                }   
+                
+                DrawSlaveFixedParts(); 
+                                
+                thread.start(ExchangeMaster);
+                thread.set_priority(osPriorityRealtime); 
+
+                SampleTicker.attach_us(&SampleIsr, CYCLE_TIME);  
+              
+                Application();
+            }
+            
+            else
+            {
+                printf("Mismatch of network units!\n");            
+                TFT.foreground(Red);                                                     
+                TFT.locate(0, 0);      
+                TFT.printf("Mismatch of network units!");
+    
+                while(1){}  
+            }                       
+        }       
+        
+        else
+        {
+            printf("No slaves found!\n");
+            TFT.foreground(Red);                                                          
+            TFT.printf("No slaves found!");             
+        
+            while(1){}  
+        }           
+    }
+    else
+    {
+        printf("Ethernet interface init failed!");
+        TFT.foreground(Red);                                                     
+        TFT.locate(0, 0);      
+        TFT.printf("Ethernet interface init failed!");                
+        while(1){}
+    }    
+}             
+                                 
+              
+//****** 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)
+        {           
+            TFT.rect(35,50, 285, 182, Red);    
+            TFT.fillrect(36,51, 284, 181, Black);
+            TFT.foreground(Red);
+            TFT.set_font((unsigned char*) Arial28x28);        
+            TFT.locate(58, 65); 
+            TFT.printf("Network error!");
+            printf("Network error!\n");                  
+            TFT.foreground(Magenta);
+            TFT.set_font((unsigned char*) Arial12x12);        
+            TFT.locate(58, 106);
+            
+            if(WorkCounterSafe >= 0)
+            {
+                TFT.printf("Expected working counter %d", ExpectWorkCounter);                                         
+                TFT.locate(58, 118);                                                   
+                TFT.printf("Actual working counter %d", WorkCounterSafe); 
+                printf("Expected working counter %d\n", ExpectWorkCounter);                                                    
+                printf("Actual working counter %d\n", WorkCounterSafe); 
+            } 
+            else
+            {
+                TFT.printf("Timeout");                 
+                printf("Timeout\n");   
+            }                        
+                
+            TFT.foreground(Green);    
+            TFT.locate(58, 142);                                                   
+            TFT.printf("Please fix the error and");
+            TFT.locate(58, 154);                      
+            TFT.printf("press the reset button");                              
+            printf("Please fix the error and press the reset button \n"); 
+            
+            SampleTicker.detach();                                  // stop the sample interrupt 
+            while(1){}                                              // and loop for ever                           
+        }     
+        
+        
+                                                                    //----- slave LAB_2_1 data management ------            
+                                                                    //    
+        Buttons_1 = in_LAB_2_1->Buttons;                            // read the buttons status from the slave  
+                                                                    //            
+        if (Buttons_1 != PrevButtons_1)                             // check if the buttons value has changed
+        {                                                           //
+            PrevButtons_1 = Buttons_1;                              // remember the current buttons value  
+            DrawButtons_1_Value(Buttons_1);                         // draw the current buttons value on the TFT                                                                                              
+        }                                                           //
+                                                                    //
+        out_LAB_2_1->Segments = Buttons_2;                          // send to the slave the buttons status
+                                                                    // from the slave LAB_2_2                  
+
+                                                                                                                    
+                                                                    
+                                                                    //----- slave 2_2 data management ----------                                                                      
+                                                                    //
+        Buttons_2 = in_LAB_2_2->Buttons;                            // read the buttons status from the slave  
+                                                                    //    
+        if (Buttons_2 != PrevButtons_2)                             // check if the buttons value has changed
+        {                                                           //
+            PrevButtons_2 = Buttons_2;                              // remember the current buttons value  
+            DrawButtons_2_Value(Buttons_2);                         // draw the current buttons value on the TFT                                                                                             
+        }                                                           //
+                                                                    //               
+        out_LAB_2_2->Segments = Buttons_1;                          // send to the slave 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;                             
+    }       
+}      
+  
+
+//******************************************************************************
+
+
+
+//******* general functions ****************************************************
+
+
+ 
+//----- draw the fixed part of the slaves visualization ------------------------
+
+void DrawSlaveFixedParts()
+{
+    int i;
+    
+    TFT.cls();                                              // clear screen    
+    TFT.line(0, 120, 340, 120, Green);                      // draw the separation line    
+                                  
+    for (i=0; i<3; i++)                                     // draw the buttons fixed parts        
+    {                                                       // for the LAB_2_1 slave   
+        TFT.circle(BUTTONS_1_X+(i*BUTTONS_1_STEP), BUTTONS_1_Y, BUTTONS_1_R, Red);                
+        TFT.circle(BUTTONS_1_X+BUTTONS_1_WIDTH+(i*BUTTONS_1_STEP), BUTTONS_1_Y, BUTTONS_1_R, Red); 
+                                                            //
+        TFT.line(BUTTONS_1_X+(i*BUTTONS_1_STEP)-BUTTONS_1_R, BUTTONS_1_Y, BUTTONS_1_X+(i*BUTTONS_1_STEP)-BUTTONS_1_R-4, BUTTONS_1_Y, Red);  
+        TFT.line(BUTTONS_1_X+BUTTONS_1_WIDTH+(i*BUTTONS_1_STEP)+BUTTONS_1_R, BUTTONS_1_Y, BUTTONS_1_X+BUTTONS_1_WIDTH+(i*BUTTONS_1_STEP)+BUTTONS_1_R+4 , BUTTONS_1_Y, Red);                          
+    }                                                       //
+                                                            //   
+    TFT.set_font((unsigned char*) Arial12x12);              // 
+    TFT.locate(BUTTONS_1_X+12, BUTTONS_1_Y+20);             // 
+    TFT.printf("LAB_2_1 Buttons");                          //      
+    
+    for (i=0; i<3; i++)                                     // draw the buttons fixed parts        
+    {                                                       // for the LAB_2_2 slave   
+        TFT.circle(BUTTONS_2_X+(i*BUTTONS_2_STEP), BUTTONS_2_Y, BUTTONS_2_R, Red);                
+        TFT.circle(BUTTONS_2_X+BUTTONS_2_WIDTH+(i*BUTTONS_2_STEP), BUTTONS_2_Y, BUTTONS_2_R, Red); 
+                                                            //
+        TFT.line(BUTTONS_2_X+(i*BUTTONS_2_STEP)-BUTTONS_2_R, BUTTONS_2_Y, BUTTONS_2_X+(i*BUTTONS_2_STEP)-BUTTONS_2_R-4, BUTTONS_2_Y, Red);  
+        TFT.line(BUTTONS_2_X+BUTTONS_2_WIDTH+(i*BUTTONS_2_STEP)+BUTTONS_2_R, BUTTONS_2_Y, BUTTONS_2_X+BUTTONS_2_WIDTH+(i*BUTTONS_2_STEP)+BUTTONS_2_R+4 , BUTTONS_2_Y, Red);                          
+    }                                                       //
+                                                            //   
+    TFT.set_font((unsigned char*) Arial12x12);              // 
+    TFT.locate(BUTTONS_2_X+12, BUTTONS_2_Y+20);             // 
+    TFT.printf("LAB_2_2 Buttons");                          //               
+                     
+    DrawButtons_1_Value (Buttons_1);                        // draw the buttons status  
+    DrawButtons_2_Value (Buttons_2);                        //            
+    
+    FirstRound = true;                      
+}    
+
+
+//---- draw the starting banner ------------------------------------------------
+
+void DrawBanner()
+{
+    TFT.set_font((unsigned char*) Arial24x23);
+    TFT.foreground(Red);
+    TFT.locate(30, 30);
+    TFT.printf("EasyCAT");
+    TFT.locate(30, 60);
+    TFT.printf("SOEM MASTER");    
+
+    TFT.foreground(Magenta);
+    TFT.locate(30, 100);
+    TFT.printf("simple example");    
+    
+    TFT.set_font((unsigned char*) Arial12x12);
+    TFT.foreground(Green);
+    TFT.locate(30, 150);
+    TFT.printf("www.bausano.net");
+
+    TFT.foreground(Green);
+    TFT.locate(30, 170);
+    TFT.printf("www.easycatshield.com"); 
+    
+    TFT.locate(30, 190);
+    TFT.printf("https://openethercatsociety.github.io/");     
+}  
+
+
+//---- slaves data visualization functions -------------------------------------
+
+void DrawButtons_1_Value (uint8_t Value)            // visualize on the TFT the
+{                                                   // slave LAB_2_1 buttons status    
+    uint8_t Slope;
+    int i;
+  
+    for (i=0; i<3; i++)
+    {
+        if ((Value & 0x04) == 0x04)
+            Slope = BUTTONS_1_R;
+        else
+            Slope = 16;          
+    
+        TFT.fillrect(BUTTONS_1_X+(i*BUTTONS_1_STEP), BUTTONS_1_Y-16-1, BUTTONS_1_X+BUTTONS_1_WIDTH+(i*BUTTONS_1_STEP), BUTTONS_1_Y-BUTTONS_1_R-1, Black);
+    
+        TFT.line(BUTTONS_1_X+(i*BUTTONS_1_STEP), BUTTONS_1_Y-BUTTONS_1_R-1, BUTTONS_1_X+BUTTONS_1_WIDTH+(i*BUTTONS_1_STEP), BUTTONS_1_Y-Slope-1, Red); 
+
+        Value = Value << 1;    
+    } 
+}    
+
+
+void DrawButtons_2_Value (uint8_t Value)            // visualize on the TFT the
+{                                                   // slave LAB_2_2 buttons status 
+    uint8_t Slope;
+    int i;
+  
+    for (i=0; i<3; i++)
+    {
+        if ((Value & 0x04) == 0x04)
+            Slope = BUTTONS_1_R;
+        else
+            Slope = 16;          
+    
+        TFT.fillrect(BUTTONS_2_X+(i*BUTTONS_2_STEP), BUTTONS_2_Y-16-1, BUTTONS_2_X+BUTTONS_2_WIDTH+(i*BUTTONS_2_STEP), BUTTONS_2_Y-BUTTONS_2_R-1, Black);
+    
+        TFT.line(BUTTONS_2_X+(i*BUTTONS_2_STEP), BUTTONS_2_Y-BUTTONS_2_R-1, BUTTONS_2_X+BUTTONS_2_WIDTH+(i*BUTTONS_2_STEP), BUTTONS_2_Y-Slope-1, Red); 
+
+        Value = Value << 1;    
+    } 
+}  
+