2

我正在尝试读取从 LIN 从节点发送的 linFrame,以识别特定位何时从零变为一。

我正在向从属伺服系统发送一条 LIN 消息,命令它移动到物理终点之外。

一旦它物理地到达终点,它的状态消息就会将一个位从零设置为一。该位标识伺服电机何时停止。我的目标是让 CAPL 脚本检测到电机已经停转。

我的命令消息是由我的 CAPL 脚本使用“output()”函数发送的。我不确定哪个函数可以读取响应,但我认为我必须发送响应消息的标头,然后读取响应帧。

variables
{
 linFrame 0x03 ACT_CTRL_MT3  = {msgChannel=1}; // actuator control command
 linFrame 0x21 ACT_STA_MT3   = {msgChannel=1}; // actuator status response

  mstimer timer1;

}


on key 'c'
{
  
  
  // command large angular position from servo at node 3
  ACT_CTRL_MT3.RTR = 0;
  ACT_CTRL_MT3.byte(0)=0x12; // section 4.5.9 of manual
  ACT_CTRL_MT3.byte(1)=0xE4;
  ACT_CTRL_MT3.byte(2)=0x14;
  ACT_CTRL_MT3.byte(3)=0xFE; // max angle
  ACT_CTRL_MT3.byte(4)=0xFF; // max angle
  ACT_CTRL_MT3.byte(5)=0x00;
  ACT_CTRL_MT3.byte(6)=0x00;
  ACT_CTRL_MT3.byte(7)=0x40;
  output(ACT_CTRL_MT3); // update command payload
  
  // Send the frame header
  ACT_CTRL_MT3.RTR = 1;
  output(ACT_CTRL_MT3);
  
  settimer(timer1,5000); // wait 5 seconds for motor to move 
}


on timer timer1{
  
  //send header of status message
  ACT_STA_MT3.RTR = 1;
  output(ACT_STA_MT3);
  
  
  write("Reading message...");
  
  //output message context
  writelineex(1,1,"FrameId=%d Length=%d, 0x%X 0x%X 0x%X 0x%X 0x%X 0x%X 0x%X 0x%X;", ACT_STA_MT3.ID, ACT_STA_MT3.DLC,
      ACT_STA_MT3.byte(0), ACT_STA_MT3.byte(1), ACT_STA_MT3.byte(2), ACT_STA_MT3.byte(3), ACT_STA_MT3.byte(4), ACT_STA_MT3.byte(5), ACT_STA_MT3.byte(6), ACT_STA_MT3.byte(7));

}

“writelinee”函数写入的数据与我在 CANalyzer 的 LIN 跟踪窗口中看到的值非常不同。

我觉得特别奇怪的是,写出的 ID 字段与代码开头变量部分中设置的 ID 不同。在代码中,我将该状态消息的帧 ID 定义为 0x21,但写入命令给出了不同的值(我相信是 0x35,尽管我目前不在我的设置中。

4

1 回答 1

1

不幸的是,我没有 CANoe 许可证,所以我无法检查我的代码是否正常工作。类似的想法我已经做过很多次了,所以我们应该很好。

正如我从您的描述中注意到的那样,您需要做三件事:

  1. 发送带有一些数据的控制 LIN 帧 (ID 0x03) 以启动电机。

  2. 发送状态 LIN 标头 (ID 0x21) - 请记住 LIN 从设备无法在 LIN 总线上启动传输,因此您需要提供 LIN 标头,以便 LIN 从设备可以响应一些数据。

  3. 从 LIN 标头获取响应数据(LIN 从设备添加到 LIN 标头 0x21 的数据) - 通知电机停转。

这是对您之前提供的代码的小修改。我还标记了哪些事情可以用不同的方式完成(你知道 CANoe 有很多功能):

variables
{
 linFrame 0x03 ACT_CTRL_MT3  = {msgChannel=1}; // actuator control command
 linFrame 0x21 ACT_STA_MT3   = {msgChannel=1}; // actuator status response
 
 mstimer timer1;
}


// starts the fun
on key 'c'  
{
  ACT_CTRL_MT3.RTR = 1;  // RTR=1 means that you want to send entire message (header + data)
  ACT_CTRL_MT3.byte(0)=0x12;
  ACT_CTRL_MT3.byte(1)=0xE4;
  ACT_CTRL_MT3.byte(2)=0x14;
  ACT_CTRL_MT3.byte(3)=0xFE;
  ACT_CTRL_MT3.byte(4)=0xFF;
  ACT_CTRL_MT3.byte(5)=0x00;
  ACT_CTRL_MT3.byte(6)=0x00;
  ACT_CTRL_MT3.byte(7)=0x40;
  output(ACT_CTRL_MT3);  // this sends the message to the bus

  settimer(timer1, 20); // set timer to trigger actions in 20 ms
}


// sending LIN headers (ID 0x21) cyclically
on timer timer1 
{
  // sends a single LIN header - you can also try to do it this way:
  // ACT_STA_MT3.RTR=0;
  // output(ACT_STA_MT3);
  linTransmitHeader(ACT_STA_MT3);  // or linTransmitHeader(0x21);
  //set timer again to let LIN Slave respond if stalled later on
  settimer(timer1, 20); // reset to execute every 20 ms
}

// event on receiving entire frame (header + response data) from LIN Slave
on linFrame ACT_STA_MT3
{
  // not sure where is located your bit that is informing about stalling of the motor, but in this example I assumed it is on first position of byte 0
  if (this.byte(0) & 0x01)
  {
    // you can put some other instructions here
    write("Motor has stalled!");
  }
  // you can also log entire frame (I think your code was fine so I copied it):
  writelineex(1,1,"FrameId=%d Length=%d, 0x%X 0x%X 0x%X 0x%X 0x%X 0x%X 0x%X 0x%X;", this.ID, this.DLC, this.byte(0), this.byte(1), this.byte(2), this.byte(3), this.byte(4), this.byte(5), this.byte(6), this.byte(7));
}

PS。试试这个,让我知道它是否像我在记事本中写的那样按预期编译和工作。我将帮助您修复潜在的错误。

于 2020-04-17T14:28:56.140 回答