preempt 内核配置

(一)PC系统信息

edda@EDDA-SH-Linux-01:~$ uname -a
Linux EDDA-SH-Linux-01 5.4.19-rt10 #1 SMP PREEMPT_RT Tue Aug 23 13:57:00 CST 2022 x86_64 x86_64 x86_64 GNU/Linux
edda@EDDA-SH-Linux-01:~$ gcc --version
gcc (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0
Copyright (C) 2017 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

(二)preempt实时包

参考:机械臂官方教程

https://frankaemika.github.io/docs/installation_linux.html#setting-up-the-real-time-kernel

(三)代码

can.cpp

can.hpp

#include <iostream>
#include <thread>
#include "can.hpp"
#include <iso646.h>

extern "C"
{
#include <ECI113.h>
#include <EciDemoCommon.h>
#include <EciCanDemo113.h>
#include <config_usbToCan_ixxat.h>
#include <ctrl_config.h>
#include <OsEci.h>
#include <ECI_pshpack1.h>
#include <string.h>
#include <limits.h>
#include <pthread.h>
#include <sched.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <unistd.h>
}

// gripPara
ECI_CTRL_HDL dwCtrlHandle = ECI_INVALID_HANDLE;
ECI_RESULT hResult = ECI_OK;
DWORD dwHwIndex = 0;
DWORD dwCtrlIndex = 0;
can_TxPDO gripCmd;
can_RxPDO gripState; // gripState
// int gripState = 0;//gripStatue
bool gripStop = false;

#if 0 
int main(int argc, char **argv) //主函数  流程切换控制
{
#if 0
    if (argc != 1)
    {
        std::cout << "Usage: " << argv[0] << " <robot-hostname>" << std::endl;
        return -1;
    }
    std::thread thrd_Grip(ThreadGrip);  
     thrd_Grip.detach();
#endif

    // gripCmd.control_word=6;
    ThreadGrip();

    return 0;
}
#endif

void *ThreadGrip(void *data);
int main(int argc, char *argv[])
{
    struct sched_param param;
    pthread_attr_t attr;
    pthread_t thread;
    int ret;

    // 获取核数
    int CPU = 0;
    int CPU_NUM = sysconf(_SC_NPROCESSORS_CONF);
    printf("System has %i processor(s). \n", CPU_NUM);
    cpu_set_t mask; // CPU核的集合

    CPU_ZERO(&mask);
    // set CPU MASK
    CPU_SET(CPU, &mask);

    /* Lock memory */
    if (mlockall(MCL_CURRENT | MCL_FUTURE) == -1)
    {
        printf("mlockall failed: %m\n");
        exit(-2);
    }

    /* Initialize pthread attributes (default values) */
    ret = pthread_attr_init(&attr);
    if (ret)
    {
        printf("init pthread attributes failed\n");
        goto out;
    }

    /* Set a specific stack size  */
    printf("PTHREAD_STACK_MIN=%d\n", PTHREAD_STACK_MIN); // 16384
    ret = pthread_attr_setstacksize(&attr, PTHREAD_STACK_MIN);
    if (ret)
    {
        printf("pthread setstacksize failed\n");
        goto out;
    }

    /* Set scheduler policy and priority of pthread */
    ret = pthread_attr_setschedpolicy(&attr, SCHED_FIFO);
    if (ret)
    {
        printf("pthread setschedpolicy failed\n");
        goto out;
    }

    param.sched_priority = 99;
    ret = pthread_attr_setschedparam(&attr, &param);
    if (ret)
    {
        printf("pthread setschedparam failed\n");
        goto out;
    }
    /* Use scheduling parameters of attr */
    ret = pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED);
    if (ret)
    {
        printf("pthread setinheritsched failed\n");
        goto out;
    }

    /* Create a pthread with specified attributes */
    ret = pthread_create(&thread, &attr, ThreadGrip, NULL);
    if (ret)
    {
        printf("create pthread failed\n");
        goto out;
    }
#if 1
    //设置当前进程的CPU Affinity

    if (pthread_setaffinity_np(thread, sizeof(mask), &mask) != 0)
    {
        printf("warning: could not set CPU affinity, continuing...\n");
    }
#endif

    /* Join the thread and wait until it is done */
    ret = pthread_join(thread, NULL);
    if (ret)
    {
        printf("join pthread failed: %m\n");
    }

out:
    return ret;
}


void *ThreadGrip(void *data) //  器械控制程序
{
    hResult = init_driver_eci(&dwHwIndex, &dwCtrlIndex, &dwCtrlHandle); // init can
    if (ECI_OK != hResult)
    {
        printf("[ERROR] init_driver ERROR!\n");
    }
    else
    {
        printf("[Note] init_driver  Success!\n");
    }

    hResult = NMTControl(dwCtrlHandle, NMT_Start_Node, 1); // start node
    if (ECI_OK != hResult)
    {
        printf("[ERROR] NMTControl ERROR!\n");
    }
    else
    {
        printf("[Note] NMTControl  Success!\n");
    }
    sleep(1);

    /*==========================================================================*/
    can_RxPDO can_RxPDO_info;
    can_RxPDO_info.state_word = 200; //任意数值
    can_RxPDO_info.act_pos = 200;
    can_RxPDO_info.act_vec = 200;
    can_RxPDO_info.act_torque = 200;
    can_RxPDO_info.act_current = 200;
    can_RxPDO_info.log_input = 200;
    can_RxPDO_info.phy_input = 200;
    can_RxPDO_info.state = 200;

    int cmdState = 0;
    int idx = 0;
    int flag = 0;

    struct timespec ts_1;
    struct timespec ts_2;
    struct timespec ts_3;
    struct timespec ts_4;
    long delta34 = 0;

    clock_gettime(CLOCK_MONOTONIC, &ts_1);
    clock_gettime(CLOCK_MONOTONIC, &ts_2);
    clock_gettime(CLOCK_MONOTONIC, &ts_3);
    clock_gettime(CLOCK_MONOTONIC, &ts_4);

    // printf("CLOCK_REALTIME   1: %d, %d\n", ts_1.tv_sec, ts_1.tv_nsec);
    // printf("CLOCK_REALTIME   2: %d, %d\n", ts_2.tv_sec, ts_2.tv_nsec);

    while (!gripStop)
    {
        // printf("idx=%d\n", idx);
        idx++;
        int a = receivePDO(dwCtrlHandle, &can_RxPDO_info); //接受PDO

        switch (cmdState)
        {
        case SwitchOnDisabled: // switch on disabled 初始化完成,可以进行CAN通讯(WP)
        {
            // printf("[SwitchOnDisabled] can_RxPDO_info.state_word=0x%x\n", can_RxPDO_info.state_word);

            if ((can_RxPDO_info.state_word & 0x0040) == 0x0040) //  0040对应的状态字是0100 0000,SwitchOnDisabled (WP)
            {
                gripCmd.control_word = 0x0006; // 06对应的含义是从初始化这一步进到下面ReadyToSwitchOn状态的控制字(WP)
                cmdState = ReadyToSwitchOn;
            }

            break;
        }

        case ReadyToSwitchOn: //该状态等待进入SwitchOn状态,此时电机没有被励磁(WP)
        {
            // printf("[ReadyToSwitchOn] can_RxPDO_info.state_word=0x%x\n", can_RxPDO_info.state_word);
            // printf("[ReadyToSwitchOn] act_pos=%d\n", can_RxPDO_info.act_pos);

            gripCmd.mode = 06; //选择运行模式为归零模式(WP)
            gripCmd.home_position = 0;
            gripCmd.homing_method = 37;                //-3 37
            gripCmd.current_threshold_of_homing = 100; // max current threshold
            gripCmd.homing_speed_for_search = 100;

            if ((can_RxPDO_info.state_word & 0x0021) == 0x0021) //  0021对应的状态字是0010 0001,就是ReadyToSwitchOn (WP)
            {
                gripCmd.control_word = 0x0007; // 07对应的含义是由等待SwitchOn状态进入到StwitchedOn状态的控制字(WP)
                cmdState = SwitchedOn;
            }
            break;
        }


       case SwitchedOn: //该状态主电已上,输入励磁信号并开始控制电机(WP)
        {
            // printf("[SwitchedOn] can_RxPDO_info.state_word=0x%x\n", can_RxPDO_info.state_word);
            // printf("[SwitchedOn] act_pos=%d\n", can_RxPDO_info.act_pos);
            // printf("[SwitchedOn] mode_display=0x%x\n", can_RxPDO_info.mode_display);

            if ((can_RxPDO_info.state_word & 0x0023) == 0x0023) // 0023对应的状态字是0010 0011,就是SwitchedOn状态(WP)
            {
                gripCmd.control_word = 0x000F; //主电上成功后,接下来进入使能状态的控制字就是0F(也就是15)(WP)
                cmdState = OperationEnabled;
            }
            break;
        }

        case OperationEnabled:
        {
            // printf("[OperationEnabled] can_RxPDO_info.state_word=0x%x\n", can_RxPDO_info.state_word);
            // printf("[OpeartionEnabled] act_pos=%d\n", can_RxPDO_info.act_pos);

            if ((can_RxPDO_info.state_word & 0x0027) == 0x0027) // 0027对应的状态字是0010 0111,就是OperationEnabled状态(WP)
            {
                cmdState = ServoSetHoming;
            }
            break;
        }

        case ServoSetHoming:
        {
            // printf("[ServoSetHoming] can_RxPDO_info.state_word=0x%x\n", can_RxPDO_info.state_word);
            // printf("[ServoSetHoming] act_pos=%d\n", can_RxPDO_info.act_pos);

            //  gripCmd.mode = 06; //选择运行模式为归零模式(WP)
            //  gripCmd.home_position = 0;
            //  gripCmd.homing_method = -3; //-3 37
            //  gripCmd.current_threshold_of_homing = 120;
            //  gripCmd.homing_speed_for_search = 100;

            if (can_RxPDO_info.mode_display == 06)
            {
                gripCmd.control_word = 0x001F; //控制字运行归零模式 0001 1111 (WP)
                cmdState = WaitingHoming;
            }
        }

       case WaitingHoming:
        {
            // printf("[WaitingHoming] can_RxPDO_info.state_word=0x%x\n", can_RxPDO_info.state_word);
            // printf("[WaitingHoming] act_pos=%d\n", can_RxPDO_info.act_pos);

            if ((can_RxPDO_info.state_word & 0x9000) == 0x9000) // 00x9000
            {
                printf(" ********** Arrive Home **********\n");
                //usleep(10000);
                // cmdState = 10;
                cmdState = ServoModeHomingEnable;

            }
            break;
        }

        case ServoModeHomingEnable:
        {

            // printf("[ServoModeHomingEnable] can_RxPDO_info.state_word=0x%x\n", can_RxPDO_info.state_word);
            // printf("[ServoModeHomingEnable] act_pos=%d\n", can_RxPDO_info.act_pos);

            // if ((can_RxPDO_info.state_word & 0x0014) == 0x0014) // 0024对应的状态字是0001 0100,operation enabled and voltage enabled (WP)
            // {
            gripCmd.target_pos = can_RxPDO_info.act_pos;
            gripCmd.mode = 8;               // set csp
            gripCmd.interpolation_time = 2; // ms 插补时间
            cmdState = ServoModeCycPosition;
            idx = 0;

            break;
        }

        case ServoModeCycPosition:
        {
            // printf("[ServoModeCycPosition] can_RxPDO_info.state_word=0x%x\n", can_RxPDO_info.state_word);
            // printf("[INFO START]flag=%d act_vec=%d\n", flag, can_RxPDO_info.act_vec);
            printf("[ServoModeCycPosition]can_RxPDO_info.act_pos=%d  \n", can_RxPDO_info.act_pos);
            printf("[ServoModeCycPosition]gripCmd.target_pos====%d  \n", 300*flag);
            printf("[ServoModeCycPosition]delta==============%d  \n", 300*flag-can_RxPDO_info.act_pos);

            // gripCmd.target_vec = 1000;

            // printf("[INFO START]flag=%d act_pos=%d\n", flag, can_RxPDO_info.act_pos);


#if 1
            if (flag < 1000)
            {
                gripCmd.target_pos +=300;
            }
            // else if (flag >= 4000 && flag < 8000)
            // { 
            // gripCmd.target_pos -= 100;
            //}
            else
            {
                cmdState = 10;
            }

#endif
            // printf("[INFO END]flag=%d act_vec=%d\n", flag, can_RxPDO_info.act_vec);
            // printf("[INFO END]flag=%d act_pos=%d\n", flag, can_RxPDO_info.act_pos);

            flag = flag + 1;

            break;
        }

        case 10:
        {
            // printf("[10] can_RxPDO_info.state_word=0x%x\n", can_RxPDO_info.state_word);
            // printf("[10] act_pos=%d\n", can_RxPDO_info.act_pos);
            gripStop = 1;

            break;
        }
        case 20:
        {
            // printf("[20] can_RxPDO_info.state_word=0x%x\n", can_RxPDO_info.state_word);

            // printf("[20] act_pos=%d\n", can_RxPDO_info.act_pos);

            cmdState = 30;
        }

        case 30:
        {
            // printf("[30] can_RxPDO_info.state_word=0x%x\n", can_RxPDO_info.state_word);
            // printf("[30] act_pos=%d\n", can_RxPDO_info.act_pos);

            gripStop = 1;
            break;
        }

        default:
            break;
        } // switch



        hResult = sendPDO(dwCtrlHandle, gripCmd, &ts_1, &ts_2, &ts_3, &ts_4, &delta34); //发送PDO
                                                                                        // usleep(2000);
    }                                                                                   // for-----while

    sleep(1);

    hResult = release_driver_eci(&dwHwIndex, &dwCtrlIndex, &dwCtrlHandle); // stop can




can.hpp

// Copyright (c) 2017 Franka Emika GmbH
// Use of this source code is governed by the Apache-2.0 license, see LICENSE
#pragma once
#include <array>
#include <iostream>
extern "C"
{
#include <ECI113.h>
#include <EciDemoCommon.h>
#include <EciCanDemo113.h>
#include <config_usbToCan_ixxat.h>
#include <ctrl_config.h>
#include <OsEci.h>
#include <ECI_pshpack1.h>
#include <string.h>
}
#define USEC_PER_SEC 1000000
#define NSEC_PER_SEC 1000000000

namespace
{
// can
#define SwitchOnDisabled 0x00
#define ReadyToSwitchOn 0x06
#define SwitchedOn 0x07
#define OperationEnabled 0x0F
#define ServoCmdDisable 0x09 // 0x07

#define ServoSetHoming 0x16 //回零模式
#define ServoModeHomingEnable 0x26
#define ServoModeHoming 0x06      //回零模式
#define ServoModeCycPosition 0x08 // 周期位置模式
#define ServoModeCycTorque 0x0A   //周期力矩模式
#define WaitingHoming 0x1000      //等待模式

#define omegaL_gripDeg_close -0.012
#define omegaL_gripDeg_open -28.4518

#define omegaR_gripDeg_close 0.012
#define omegaR_gripDeg_open 28.4518

#define HomingModeNegative -3           //正向回零
#define HomingModeNegativeToPositive -1 //正向回零再反转
#define HomingModePositive -4           //反向回零
#define HomingModePositiveToNegative -2 //负向回零再正转

#define NMT_Start_Node 0x01
#define NMT_Stop_Node 0x02
#define NMT_Enter_PreOperational 0x80
#define NMT_Reset_Node 0x81
#define NMT_Reset_Comunication 0x82


  typedef struct CAN_TxPDO
  {
    uint16_t control_word;
    int32_t target_pos;
    int32_t target_vec;
    int32_t home_position;
    int16_t target_torque;
    int8_t homing_method;
    int8_t mode;
    int8_t state;
    int16_t current_threshold_of_homing;
    int32_t homing_speed_for_search;
    uint8_t interpolation_time;
  } can_TxPDO;
  typedef struct CAN_RxPDO
  {
    uint16_t state_word;
    int8_t mode_display;
    int32_t act_pos;
    int32_t act_vec;
    int16_t act_torque;
    int16_t act_current;
    uint8_t log_input;
    uint8_t phy_input;
    int8_t state;
  } can_RxPDO;
  // can

  static long cycs = 0;
  static inline void tsnorm(struct timespec *ts)
  {
    while (ts->tv_nsec >= NSEC_PER_SEC)
    {
      ts->tv_nsec -= NSEC_PER_SEC;
      ts->tv_sec++;
    }
  }
  ECI_RESULT NMTControl(ECI_CTRL_HDL dwCtrlHandle, BYTE NMT_CMD, BYTE Node_Id)
  {
    ECI_RESULT hResult = ECI_OK;
    ECI_CTRL_MESSAGE stcCtrlMsg = {0};
    //*** Prepare CAN Message to send
    stcCtrlMsg.wCtrlClass = ECI_CTRL_CAN;
    stcCtrlMsg.u.sCanMessage.dwVer = ECI_STRUCT_VERSION_V0;
    stcCtrlMsg.u.sCanMessage.u.V0.dwMsgId = 0x000;
    stcCtrlMsg.u.sCanMessage.u.V0.uMsgInfo.Bits.dlc = 2;
    stcCtrlMsg.u.sCanMessage.u.V0.abData[0] = NMT_CMD;
    stcCtrlMsg.u.sCanMessage.u.V0.abData[1] = Node_Id;
    OS_Sleep(1);
    //*** Send one message
    hResult = ECI113_CtrlSend(dwCtrlHandle, &stcCtrlMsg, ECIDEMO_TX_TIMEOUT);
    OS_Sleep(10);
   /***************************************************/
    if (ECI_OK != hResult)
    {
      OS_Printf("Error while sending CAN Messages\n");
      ECIDEMO_CHECKERROR(ECI113_CtrlSend);
    }
    return hResult;
  }

  int receivePDO(ECI_CTRL_HDL dwCtrlHandle, can_RxPDO *can_RxPDO_info)
  {
    // printf("file=%s func=%s line=%d\n", __FILE__, __FUNCTION__, __LINE__);

#if 0
    can_RxPDO_info->state_word = 0;
    can_RxPDO_info->act_pos = 0;
    can_RxPDO_info->act_vec = 0;
    can_RxPDO_info->act_torque = 0;
    can_RxPDO_info->act_current = 0;
    can_RxPDO_info->log_input = 0;
    can_RxPDO_info->phy_input = 0;
    can_RxPDO_info->state = 0;
#endif

    ECI_CTRL_MESSAGE astcCtrlMsg[20] = {{0}};
    DWORD dwCount = _countof(astcCtrlMsg);
    DWORD dwMsgIndex = 0;
    ECI_RESULT hResult = ECI_OK;
    //*** Try to read some message

    hResult = ECI113_CtrlReceive(dwCtrlHandle, &dwCount, astcCtrlMsg, ECIDEMO_RX_TIMEOUT);

    if (ECI_OK != hResult)
    {
      printf("[reseive_PDO_ERROR]\n");
      ECIDEMO_CHECKERROR(ECI113_CtrlReceive);
      printf("\n");
      can_RxPDO_info->state = 1;
      return 0;
    }
    while ((ECI_OK == hResult) && (dwCount > dwMsgIndex))
    {
      ECI_CTRL_MESSAGE *pstcCtrlMsg = &astcCtrlMsg[dwMsgIndex];
      DWORD b1 = pstcCtrlMsg->u.sCanMessage.u.V0.dwMsgId;
      uint8_t *abData = pstcCtrlMsg->u.sCanMessage.u.V0.abData;
      // printf("[INFO]dwMsgIndex=%d COBID=0x%x\n",dwMsgIndex, b1);

      // EciPrintCtrlMessage(&astcCtrlMsg[dwMsgIndex]);
      // OS_Printf("\n");


      // EciPrintCtrlMessage(&astcCtrlMsg[dwMsgIndex]);
      // OS_Printf("\n");
      int nodeID = 0x01;
      if (b1 == 0x180 + nodeID)
      {
        memcpy(&can_RxPDO_info->state_word, &abData[0], 2);
        memcpy(&can_RxPDO_info->mode_display, &abData[2], 4);

        // EciPrintCtrlMessage(&astcCtrlMsg[dwMsgIndex]);
        // OS_Printf("\n");
      }
      else if (b1 == 0x280 + nodeID)
      {
        memcpy(&can_RxPDO_info->state_word, &abData[0], 2);
        memcpy(&can_RxPDO_info->act_pos, &abData[2], 4);
        // EciPrintCtrlMessage(&astcCtrlMsg[dwMsgIndex]);
        // OS_Printf("\n");
        // printf("act_pos=%d\n",can_RxPDO_info->act_pos);
      }
      else if (b1 == 0x380 + nodeID)

      {
        memcpy(&can_RxPDO_info->state_word, &abData[0], 2);
        memcpy(&can_RxPDO_info->act_vec, &abData[2], 4);
        // EciPrintCtrlMessage(&astcCtrlMsg[dwMsgIndex]);
        //  OS_Printf("\n");
      }
      else if (b1 == 0x480 + nodeID)
      {
        memcpy(&can_RxPDO_info->state_word, &abData[0], 2);
        memcpy(&can_RxPDO_info->act_torque, &abData[2], 2);
        memcpy(&can_RxPDO_info->act_current, &abData[4], 2); //
        //    EciPrintCtrlMessage(&astcCtrlMsg[dwMsgIndex]);
        //   OS_Printf("\n");
        //   printf("state_word=%d  act_torque=%d  act_current=%d  \n",can_RxPDO_info->state_word,can_RxPDO_info->act_torque,can_RxPDO_info->act_current);
      }
      else if ((b1 != 0x180 + nodeID) && (b1 != 0x280 + nodeID) && (b1 != 0x380 + nodeID) && (b1 != 0x480 + nodeID))
      {
        printf("[reseive_PDO_ERROR]: receiveMessage failed!");
        EciPrintCtrlMessage(&astcCtrlMsg[dwMsgIndex]);
        OS_Printf("\n");
        can_RxPDO_info->state = 2;
      }
      //*** Proceed with next message
      dwMsgIndex++;
    } // end while
    //*** Reset Error code and proceed with transmission
    hResult = ECI_OK;
    return 0;
  } //主函数


  HRESULT sendPDO(ECI_CTRL_HDL dwCtrlHandle, can_TxPDO canTxPDO, struct timespec *ts_1, struct timespec *ts_2, struct timespec *ts_3, struct timespec *ts_4, long *delta34)
  {
    // printf("file=%s func=%s line=%d\n", __FILE__, __FUNCTION__, __LINE__);

    ECI_RESULT hResult = ECI_OK;
    /***********************************************************************/
    //*** Send some CAN Messages
    ECI_CTRL_MESSAGE stcCtrlMsg = {0};
    DWORD dwTxMsgCount = 5; // ECIDEMO_TX_MSGCOUNT_CAN;
    DWORD dwIndex = 0;
    //*** Send Loop
    for (dwIndex = 0; dwIndex < dwTxMsgCount; dwIndex++)
    {
      //*** Prepare CAN Message to send
      stcCtrlMsg.wCtrlClass = ECI_CTRL_CAN;
      stcCtrlMsg.u.sCanMessage.dwVer = ECI_STRUCT_VERSION_V0;
      stcCtrlMsg.u.sCanMessage.u.V0.uMsgInfo.Bits.dlc = 8;
      uint8_t *abData = stcCtrlMsg.u.sCanMessage.u.V0.abData;
      // OS_Sleep(200);
      int nodeID = 0x01;
      if (dwIndex == 0)
      {
        stcCtrlMsg.u.sCanMessage.u.V0.dwMsgId = 0x200 + nodeID;
        memcpy(&abData[0], &(canTxPDO.control_word), 2);
        memcpy(&abData[2], &(canTxPDO.mode), 1);
        memcpy(&abData[3], &(canTxPDO.homing_method), 1);
        // mempcp(&abData[4],&(canTxPDO.home_position),4);
      }
      if (dwIndex == 1)
      {
        stcCtrlMsg.u.sCanMessage.u.V0.dwMsgId = 0x300 + nodeID;
        memcpy(&(abData[0]), &(canTxPDO.control_word), 2);
        memcpy(&(abData[2]), &(canTxPDO.target_pos), 4);
        memcpy(&(abData[6]), &(canTxPDO.current_threshold_of_homing), 2);
      }
      if (dwIndex == 2)
      {
        stcCtrlMsg.u.sCanMessage.u.V0.dwMsgId = 0x400 + nodeID;
        memcpy(&(abData[0]), &(canTxPDO.control_word), 2);
        memcpy(&(abData[2]), &(canTxPDO.target_vec), 4);
        memcpy(&(abData[6]), &(canTxPDO.interpolation_time), 1);
      }

      if (dwIndex == 3)
      {
        stcCtrlMsg.u.sCanMessage.u.V0.dwMsgId = 0x500 + nodeID;
        memcpy(&(abData[0]), &(canTxPDO.control_word), 2);
        memcpy(&(abData[2]), &(canTxPDO.target_torque), 2);
        memcpy(&(abData[4]), &(canTxPDO.homing_speed_for_search), 4);
      }


      if (dwIndex == 4)
      {
        stcCtrlMsg.u.sCanMessage.u.V0.dwMsgId = 0x080;
        stcCtrlMsg.u.sCanMessage.u.V0.uMsgInfo.Bits.dlc = 0;

//plan A
#if 1
        long time = 2000000; // 5000000ns=5ms

        long delta_nsec,  delta_sec;
        long remain_ns = 0;

        /* Get current time */
        clock_gettime(CLOCK_MONOTONIC, ts_2);

        delta_sec = ts_2->tv_sec - ts_1->tv_sec;
        delta_nsec = delta_sec * 1000000000 + ts_2->tv_nsec - ts_1->tv_nsec; //+ *delta34;
        remain_ns = time - delta_nsec > 10000  ? time - delta_nsec : 10000;


        //printf("used_ns=%lu  remain_ns=%lu\n", delta_nsec, remain_ns);


        ts_2->tv_nsec += remain_ns;
        tsnorm(ts_2);
        ts_1->tv_sec = ts_2->tv_sec;
        ts_1->tv_nsec = ts_2->tv_nsec;

        int ret = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, ts_2, NULL);
        hResult = ECI113_CtrlSend(dwCtrlHandle, &stcCtrlMsg, ECIDEMO_TX_TIMEOUT);
#endif



//plan B
#if 0
        ts_2->tv_nsec += 1950000;
        tsnorm(ts_2);

        int ret = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, ts_2, NULL);
        hResult = ECI113_CtrlSend(dwCtrlHandle, &stcCtrlMsg, ECIDEMO_TX_TIMEOUT);
#endif




        break;
      } // if (dwIndex == 4)

      //*** Wait some time to ensure bus idle
      // OS_Sleep(1);
      //*** Send one message
      hResult = ECI113_CtrlSend(dwCtrlHandle, &stcCtrlMsg, ECIDEMO_TX_TIMEOUT);
      if (ECI_OK != hResult)
      {
        printf("[PDOSendERROR]: /n");
        ECIDEMO_CHECKERROR(ECI113_CtrlSend);
        printf("/n");
      }
    } // end for for (dwIndex = 0; dwIndex < dwTxMsgCount; dwIndex++)

    return hResult;
  }

  DWORD ReadSDO(ECI_CTRL_HDL dwCtrlHandle, WORD index, BYTE Subindex, BYTE dCount)
  {
    ECI_RESULT hResult = ECI_OK;
    ECI_CTRL_MESSAGE stcCtrlMsg = {0};
    DWORD SDO_info;
    stcCtrlMsg.wCtrlClass = ECI_CTRL_CAN;
    stcCtrlMsg.u.sCanMessage.dwVer = ECI_STRUCT_VERSION_V0;
    stcCtrlMsg.u.sCanMessage.u.V0.dwMsgId = 0x601;
    stcCtrlMsg.u.sCanMessage.u.V0.uMsgInfo.Bits.dlc = 8;
    uint8_t *abData = stcCtrlMsg.u.sCanMessage.u.V0.abData;
    abData[0] = 0x40;
    memcpy(&abData[1], &(index), 2);
    memcpy(&abData[3], &(Subindex), 1);
    abData[4] = 0;
    abData[5] = 0;
    abData[6] = 0;
    abData[7] = 0;
    hResult = ECI113_CtrlSend(dwCtrlHandle, &stcCtrlMsg, ECIDEMO_TX_TIMEOUT);
    if (ECI_OK != hResult)
    {
      printf("[PDOSendERROR]: \n");
      ECIDEMO_CHECKERROR(ECI113_CtrlSend);
      printf("/n");
      return 0;
    }
    OS_Sleep(5);

    ECI_CTRL_MESSAGE astcCtrlMsg[20] = {{0}};
    DWORD dwCount = _countof(astcCtrlMsg);
    hResult = ECI113_CtrlReceive(dwCtrlHandle, &dwCount, astcCtrlMsg, ECIDEMO_RX_TIMEOUT);
    if (ECI_OK != hResult)
    {
      printf("[PDOSendERROR]: \n");
      ECIDEMO_CHECKERROR(ECI113_CtrlReceive);
      printf("/n");
      return 0;
    }
    else
    {
      ECI_CTRL_MESSAGE *pstcCtrlMsg = &astcCtrlMsg[0];
      DWORD cobID = pstcCtrlMsg->u.sCanMessage.u.V0.dwMsgId;
      uint8_t *SDOData = pstcCtrlMsg->u.sCanMessage.u.V0.abData;

      // EciPrintCtrlMessage(&astcCtrlMsg[dwMsgIndex]);
      // OS_Printf("\n");
      if (cobID == 0x581)
      {
        memcpy(&SDO_info, &abData[4], 4);
        return SDO_info;
      }
    }
    return SDO_info;
  }

  ECI_RESULT WriteSDO(ECI_CTRL_HDL dwCtrlHandle, BYTE index, BYTE Subindex, BYTE length, DWORD data)
  {
    ECI_RESULT hResult = ECI_OK;

    ECI_CTRL_MESSAGE stcCtrlMsg = {0};
    stcCtrlMsg.wCtrlClass = ECI_CTRL_CAN;
    stcCtrlMsg.u.sCanMessage.dwVer = ECI_STRUCT_VERSION_V0;
    stcCtrlMsg.u.sCanMessage.u.V0.dwMsgId = 0x601;
    stcCtrlMsg.u.sCanMessage.u.V0.uMsgInfo.Bits.dlc = 8;
    uint8_t *abData = stcCtrlMsg.u.sCanMessage.u.V0.abData;
    abData[0] = length;
    memcpy(&abData[1], &(index), 2);
    memcpy(&abData[3], &(Subindex), 1);
    if (length == 0x2F)
    {
      memcpy(&abData[4], &(data), 1);
    }
    if (length == 0x2B)
    {
      memcpy(&abData[4], &(data), 2);
    }
    if (length == 0x27)
    {
      memcpy(&abData[4], &(data), 3);
    }
    if (length == 0x23)
    {
      memcpy(&abData[4], &(data), 4);
    }
    hResult = ECI113_CtrlSend(dwCtrlHandle, &stcCtrlMsg, ECIDEMO_TX_TIMEOUT);

    if (ECI_OK != hResult)
    {
      printf("[PDOSendERROR]:\n");
      ECIDEMO_CHECKERROR(ECI113_CtrlSend);
      printf("/n");
      return 0;
    }
    return 0;
  }

} // namespace name
                     

          






  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值