使用 QEC-M-043T 控制 EtherCAT 數位 I/O 從站模組,監控內部信息

本教程將教您使用QEC-M控制QEC-RxxD(EtherCAT數位I/O從站模組)系列產品。 該項目是 EtherCAT 主站和 EtherCAT 從站控制和監視器的簡單演示。

qecm043tControlQecr00d

目標:

在本教程中,我們將實現以下目標:

  • 讓使用者了解 EtherCAT 函式庫
  • 連接 QEC-M 和 QEC-R
  • 創建一個使用者界面,去顯示裝置的狀態和設備的數據

所需的硬體和軟體:


開始本教程

首先使用 USB 轉 Micro USB 電纜將 QEC-M-043T 連線至個人電腦,並開啟 86Duino IDE 500。如果這是您第一次運行 86Duino sketch,我們建議您在繼續之前查看如何為86Duino設置QEC-M-043T

步驟 1. 連接 QEC-M 和 QEC-RxxD

  1. 使用 RJ45 連接 QEC-M 和 QEC-RxxD。
  2. 連接由 Vp(外圍電源)供電的 QEC-R11D0F 和 QEC-R11DF0 之間。
qecm043tControlQecr00d_img1

步驟 2. 將以下給定代碼複製到 86Duino IDE

#include "EthercatMaster.h"
#include <lvgl86.h>

EthercatMaster master;

DmpQECR11D0FSDriver QECR11D0FS;
DmpQECR11DF0DDriver QECR11DF0D;
uint16_t val = 0x5555;

void lv_demo_widgets(void); /* lvgl User Interface work */
static void tab_create_1(lv_obj_t * parent);
static void tab_create_2(lv_obj_t * parent);
static void color_chg_event_cb(lv_obj_t * sw, lv_event_t e);

static lv_obj_t * tv;
static lv_obj_t * t[2];
static lv_obj_t * led[32];
static lv_obj_t * label_system[8];
static lv_obj_t * gauge[3];
static lv_obj_t * label_gauge[3];
static lv_style_t bigStyle;
static lv_style_t style_box;
static lv_style_t style_ledColor;
static lv_color_t needle_colors = LV_COLOR_RED;

const char tabName[2][50] = {"Light Status", "Device Information"};
const char led_lightName[2][50] = {"QECR11D0FS LED Light", "QECR11DF0S LED Light"};
const char value_systemName[8][50] = {"QECR11D0FS Voltage-s", "QECR11D0FS Current-s", "QECR11D0FS Voltage-p", "QECR11D0FS Current-p",
                                    "QECR11DF0D Voltage-s", "QECR11DF0D Current-s", "QECR11DF0D Voltage-p", "QECR11DF0D Current-p",
                                    };
const char value_systemTempName[3][50] = {"QECR11D0FS Temp.", "QECR11DF0D Temp.", "Master CPU Temp."};                  
const int ledLocateX[32] = {350, 250, 150, 50, -50, -150, -250, -350,
                          350, 250, 150, 50, -50, -150, -250, -350,
                          350, 250, 150, 50, -50, -150, -250, -350,
                          350, 250, 150, 50, -50, -150, -250, -350,
                          };
const int ledLocateY[32] = {150, 150, 150, 150, 150, 150, 150, 150,
                          50, 50, 50, 50, 50, 50, 50, 50,
                          -50, -50, -50, -50, -50, -50, -50, -50,
                          -150, -150, -150, -150, -150, -150, -150, -150,
                          };
long unsigned int ledStyleColor = 0x60ff4e;
unsigned long timeCheck = 0;
bool ledSw[32];

void setup(void) {
    Serial.begin(115200); // Serial Port begin
    // GUI: LVGL
    lv86_init(); // Init LV86
    lv_disp_size_t disp_size = lv_disp_get_size_category(NULL);
    lv_demo_widgets();
    // EtherCAT
    master.begin();
    QECR11D0FS.begin(0, master);
    QECR11DF0D.begin(1, master);
    /* Auto FreeRun Mode, Cycle Time 500000 ns. */
    master.start(ECAT_AUTO, 500000);
    // Timing
    timeCheck = millis();
}

void loop() {
    lv_task_handler(); /* let the GUI do its work */
    escGpioControl(); /* EtherCAT Slave - GPIN/OUT control */
    label_system_value(); /* label Value Setting */
    ledSystemControl(); /* led control */
}

void lv_demo_widgets(void) {
    double light_palette[49] = {
    0x01a2b1,
    0x44d1b6,
    0x01a2b1,
    0xff0000,
    0x01a2b1,
    0xff0000,
    0x01a2b1,
    0xff0000,
    0x01a2b1,
    0xff0000,
    0x01a2b1,
    0xff0000,
    0x01a2b1,
    0xff0000,
    0x01a2b1,
    0xff0000,
    0x01a2b1,
    0xff0000,
    0x01a2b1,
    0xff0000,
    0x01a2b1,
    0xff0000,
    0x01a2b1,
    0xff0000,
    
    0xeaeff3,
    0xffffff,
    0xeeeeee,
    0x3b3e42,
    0x3b3e42,
    0xffffff,
    0x3b3e42,
    0xd6dde3,
    0x3b3e42,
    0xaaaaaa,
    0xd6dde3,
    0xffffff,
    0x888888,
    0xcccccc,
    0xd4d7d9,
    0x666666,
    0xaaaaaa,
    0x464b5b,
    0x888888,
    -2,
    0xc0c0c0,
    0xcccfd1,
    -1,//sw_knob
    0xffffff,
    0x888888};
    
    static lv_font_t * theme_fonts[6] = {
    &lv_font_montserrat_18,
    &lv_font_montserrat_14,
    &lv_font_montserrat_36,
    &lv_font_montserrat_12,
    &lv_font_montserrat_28,
    &lv_font_montserrat_18};

    // Setting Theme
    lv_theme_material86_init(light_palette, theme_fonts);

    // Create Tabview paging object
    tv = lv_tabview_create(lv_scr_act(), NULL);
    
    lv_obj_set_style_local_pad_left(tv, LV_TABVIEW_PART_TAB_BG, LV_STATE_DEFAULT, LV_HOR_RES / 2);

    // Create a switch element in the upper left corner
    lv_obj_t * sw = lv_switch_create(lv_scr_act(), NULL);
    lv_obj_set_event_cb(sw, color_chg_event_cb);
    lv_obj_set_pos(sw, LV_DPX(10), LV_DPX(10));
    lv_obj_set_style_local_value_str(sw, LV_SWITCH_PART_BG, LV_STATE_DEFAULT, " ");
    lv_obj_set_style_local_value_align(sw, LV_SWITCH_PART_BG, LV_STATE_DEFAULT, LV_ALIGN_OUT_RIGHT_MID);
    lv_obj_set_style_local_value_ofs_x(sw, LV_SWITCH_PART_BG, LV_STATE_DEFAULT, LV_DPI/35);
    lv_switch_off(sw, LV_ANIM_ON);
    
    // Create Tabpage title
    for (int i = 0; i < 2; i++) {
      t[i] = lv_tabview_add_tab(tv, tabName[i]);
    }

    // Create Tabpage content
    tab_create_1(t[0]); // Tabpage 1 content
    tab_create_2(t[1]); // Tabpage 2 content    
 
}

static void tab_create_1(lv_obj_t * parent) {
    // Tabpage 1 content

    lv_page_set_scrl_layout(parent, LV_LAYOUT_PRETTY_TOP);

    lv_disp_size_t disp_size = lv_disp_get_size_category(NULL);
    lv_coord_t grid_w = lv_page_get_width_grid(parent, disp_size <= LV_DISP_SIZE_SMALL ? 1 : 2, 1);

    lv_style_init(&style_ledColor);
    lv_style_set_text_font(&bigStyle ,LV_STATE_DEFAULT, &lv_font_montserrat_28);

    lv_style_set_bg_color(&style_ledColor, LV_STATE_DEFAULT, lv_color_hex(ledStyleColor));
    lv_style_set_shadow_color(&style_ledColor, LV_STATE_DEFAULT, lv_color_hex(ledStyleColor));
    lv_style_set_border_color(&style_ledColor, LV_STATE_DEFAULT, lv_color_hex(ledStyleColor));

    for (int j = 0; j < 2; j++) {
      lv_obj_t * h = lv_cont_create(parent, NULL);
      lv_cont_set_layout(h, LV_LAYOUT_PRETTY_MID);
      lv_obj_add_style(h, LV_CONT_PART_MAIN, &style_box);
      lv_obj_set_drag_parent(h, true);

      lv_cont_set_fit2(h, LV_FIT_NONE, LV_FIT_TIGHT);
      lv_obj_set_width(h, grid_w);
      lv_obj_set_style_local_value_str(h, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, NULL);
  
      lv_obj_t * label = lv_label_create(h, NULL);
      lv_label_set_text(label, led_lightName[j]);
      lv_obj_align(label, h, LV_ALIGN_IN_TOP_MID, 0, 0);
      lv_obj_add_style(label, LV_LABEL_PART_MAIN, &bigStyle);

      if (j == 0) {
        for (int i = 0; i < 16; i++) {
          led[i]  = lv_led_create(h, NULL);
          lv_obj_align(led[i], h, LV_ALIGN_CENTER, ledLocateX[i], ledLocateY[i]);
          lv_obj_add_style(led[i], LV_OBJ_PART_MAIN, &style_ledColor);
          lv_obj_set_size(led[i], 50, 50);
          lv_led_set_bright(led[i], 64);
        }
      } else {
        for (int i = 16; i < 32; i++) {
          led[i]  = lv_led_create(h, NULL);
          lv_obj_align(led[i], h, LV_ALIGN_CENTER, ledLocateX[i], ledLocateY[i]);
          lv_obj_add_style(led[i], LV_OBJ_PART_MAIN, &style_ledColor);
          lv_obj_set_size(led[i], 50, 50);
          lv_led_set_bright(led[i], 64);
        }
      }
    }
}

static void tab_create_2(lv_obj_t * parent) {
    // Tabpage 2 content
    lv_page_set_scrl_layout(parent, LV_LAYOUT_PRETTY_TOP);

    lv_disp_size_t disp_size = lv_disp_get_size_category(NULL);
    lv_coord_t grid_w = lv_page_get_width_grid(parent, disp_size <= LV_DISP_SIZE_SMALL ? 1 : 2, 1);

    lv_style_init(&bigStyle);
    lv_style_set_text_font(&bigStyle ,LV_STATE_DEFAULT, &lv_font_montserrat_28);
    
    for (int i = 0; i < 8; i++) {
        lv_obj_t * h = lv_cont_create(parent, NULL);
        lv_cont_set_layout(h, LV_LAYOUT_PRETTY_MID);
        lv_obj_add_style(h, LV_CONT_PART_MAIN, &style_box);
        lv_obj_set_drag_parent(h, true);

        lv_cont_set_fit2(h, LV_FIT_NONE, LV_FIT_TIGHT);
        lv_obj_set_width(h, grid_w);
        lv_obj_set_style_local_value_str(h, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, NULL);

        lv_obj_t * label = lv_label_create(h, NULL);
        lv_label_set_text(label, value_systemName[i]);
        lv_obj_align(label, h, LV_ALIGN_IN_TOP_MID, 0, 0);
        lv_obj_add_style(label, LV_LABEL_PART_MAIN, &bigStyle);

        label_system[i] = lv_label_create(h, NULL);
        lv_label_set_text(label_system[i], "Error");
        lv_obj_align(label_system[i], h, LV_ALIGN_IN_TOP_MID, 0, 0);
        lv_obj_add_style(label_system[i], LV_LABEL_PART_MAIN, &bigStyle);
      }
    for (int i = 0; i < 3; i++) {
        lv_obj_t * h = lv_cont_create(parent, NULL);
        lv_cont_set_layout(h, LV_LAYOUT_PRETTY_MID);
        lv_obj_add_style(h, LV_CONT_PART_MAIN, &style_box);
        lv_obj_set_drag_parent(h, true);

        lv_cont_set_fit2(h, LV_FIT_NONE, LV_FIT_TIGHT);
        lv_obj_set_width(h, grid_w);
        lv_obj_set_style_local_value_str(h, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, NULL);

        lv_obj_t * label = lv_label_create(h, NULL);
        lv_label_set_text(label, value_systemTempName[i]);
        lv_obj_align(label, h, LV_ALIGN_IN_TOP_MID, 0, 0);
        lv_obj_add_style(label, LV_LABEL_PART_MAIN, &bigStyle);
      
      	gauge[i] = lv_gauge_create(h, NULL);
      	lv_obj_align(gauge[i], h, LV_ALIGN_CENTER, 0, 0);
      	lv_gauge_set_value(gauge[i], 0, 10);
      	lv_gauge_set_needle_count(gauge[i], 1, &needle_colors);

        label_gauge[i] = lv_label_create(gauge[i], NULL);
        lv_label_set_text(label_gauge[i], "Error");
        lv_obj_align(label_gauge[i], gauge[i], LV_ALIGN_IN_BOTTOM_MID, -20, -20);
        lv_obj_add_style(label_gauge[i], LV_LABEL_PART_MAIN, &bigStyle);
      }
}

static void color_chg_event_cb(lv_obj_t * sw, lv_event_t e) {
    // Here is the action of the switch in the upper left corner
}

void escGpioControl(void) {
    while ((millis() - timeCheck) > 1000) { // per 1 second
      timeCheck = millis();
      for (int i = 0; i < 16; i++) {
        QECR11D0FS.digitalWrite(i, ((val >> abs(i-15)) & 0x01));
        QECR11DF0D.digitalRead(i);
        ledSw[i] = ((val >> abs(i-15)) & 0x01);
      }

      val = ~val;
    }
}

void label_system_value(void) {
  /*
  DmpQECR11D0FSDriver QECR11D0FS;
  DmpQECR11DF0DDriver QECR11DF0D;
  */
  float textValue[11];
  char textValueChar[11][100];
  textValue[0] = QECR11D0FS.getSystemPowerVoltage();
  textValue[1] = QECR11D0FS.getSystemPowerCurrent();
  textValue[2] = QECR11D0FS.getPeripheralPowerVoltage();
  textValue[3] = QECR11D0FS.getPeripheralPowerCurrent();
  textValue[4] = QECR11DF0D.getSystemPowerVoltage();
  textValue[5] = QECR11DF0D.getSystemPowerCurrent();
  textValue[6] = QECR11DF0D.getPeripheralPowerVoltage();
  textValue[7] = QECR11DF0D.getPeripheralPowerCurrent();

  for (int i = 0; i < 8; i++) {
    sprintf(textValueChar[i], "%5.2f", textValue[i]);
    if (lv_label_get_text(label_system[i]) != textValueChar[i]) lv_label_set_text(label_system[i], textValueChar[i]);
  }

  float gaugeValue[3];
  char gaugeValueChar[3][100];
  gaugeValue[0] = QECR11D0FS.getTemperature();
  gaugeValue[1] = QECR11DF0D.getTemperature();
  gaugeValue[2] = cpuTemperature();

  for (int j = 0; j < 3; j++) {
    sprintf(gaugeValueChar[j], "%5.2f", gaugeValue[j]);
    if (lv_gauge_get_value(gauge[j], 0) != gaugeValue[j]) lv_gauge_set_value(gauge[j], 0, gaugeValue[j]);
    if (lv_label_get_text(label_gauge[j]) != gaugeValueChar[j]) lv_label_set_text(label_gauge[j], gaugeValueChar[j]);
  }
}

void ledSystemControl(void) {
  for (int i = 0; i < 32; i++) {
    // setting light status: digital input
    if (i >= 16) ledSw[i] = QECR11DF0D.digitalRead(i-16);
    // display light status
    if (ledSw[i]) {lv_led_on(led[i]);}
    if (!ledSw[i]) {lv_led_off(led[i]);}    
  }
}

步驟 3. 上傳您的草稿碼!

點擊驗證按鈕旁邊的右箭頭按鈕(上傳)。 代碼上傳後,您可以在 QEC-M 的人機界面上看到您設計的畫面。

  • 燈號畫面用於 LED 狀態顯示,它將檢測硬件狀態以將其顯示在用戶界面上。
  • 設備信息畫面用於內部監視器信息,由軟體配置。 此演示中有電壓、電流和溫度。

結論

本教程介紹如何使用 QEC-M-043T 控制 EtherCAT 從站數位 I/O 模組,並監控其內部信息。 您可以學習 EtherCAT 函式庫與 LVGL (輕量型人機介面函式庫) 結合起來製作一個應用程式,並使用一種非常簡單的方式來顯示機台信息。

請繼續關注 QEC 的更多項目!

如果您有任何疑問/疑問,請隨時發表評論!


86Duino 參考的文本是根據 知識共享署名-相同方式分享 3.0 許可證,部分文本是從 Arduino 參考 修改的。 參考中的代碼示例已發佈到公共領域。

返回頂端