技术博客

31/01/2022 作者 Prachi Patel

使用外部触发器输入和输出引脚作为数字I/O

此博客中谈到的功能已在下列产品上进行了测试:

Kvaser Memorator Pro 5xHS         EAN: 73-30130-00778-9
Kvaser Memorator Pro 2xHS v2    EAN: 73-30130-00819-9

Kvaser的Windows驱动程序  V5.35
Kvaser CANlib SDK                V5.35

测试前的准备

要使用触发器引脚进行测试,你当然需要Kvaser Memorator Pro。
你不需要GPS/Arduino测试板,但信号发生器在测试时非常便捷。如果你想看到不同信号之间的关联,示波器也是很好的选择。

为什么使用Memorator触发器I/O引脚?

在一些情况下,你可能需要检测数字信号,或者需要在特定状况出现时发送数字信号。Memorator不可能取代PLC或高级I/O部件,但在某些情况下,一个数字通道就足够了。

摘自产品使用说明:

Kvaser Memorator Pro 2xHS v2可设置为通过外部信号触发,还可配置为在下降沿和上升沿上触发。

Kvaser Memorator Pro 2xHS v2可设置为通过外部触发器输出引脚,发送外部脉冲。

在通道CAN1上有一个触发器输入,在通道CAN2上有一个触发器输出。两者都是5V逻辑,可使用TTL电平。它们的目的是规定当一个特定事件发生时,执行一个具体类型的操作。

当Kvaser推出 Kvaser DIN Rail SE400S-X10,及其附加模块时,包括支持Kvaser Memorator Pro v2设备上处理I/O引脚。我们现在可以直接控制Kvaser Memorator Pro设备上的数字输入和输出。

可使用CAN1上的触发器输入和CAN2上的触发器输出,作为通过CANLib或t程序控制的数字I/O。

在本文中,我将展示如何进行此操作,以及我们可以通过I/O引脚获得的一些信息。

我将使用Kvaser t编程演示,但也可以使用CANlib。使用CANLib的步骤与使用t编程基本相同。

你可以在此处查看t编程使用手册:

https://www.kvaser.com/download/?utm_source=software&utm_ean=7330130980327&utm_status=latest

有关CANLib I/O函数的一些实用信息;

https://www.kvaser.com/canlib-webhelp/page_user_guide_kviopin.html

1我的信号发生器和测试设置

为了能够显示数字信号的表现,我必须有一个信号发生器以生成数字信号。我将使用示波器显示CAN帧和数字信号之间的关系。

我使用一台小型Arduino电脑,它连接到一个GPS模块和一个MCP2515模块(CAN控制器)。

GPS生成1PPS(每秒1个脉冲)信号[绿线]。该信号连接到Arduino上的一个数字输入和我的示波器。

每次GPS发送1PPS信号时,Arduino都会产生35毫秒长的脉冲[红线]。此脉冲被发送至Memorator Pro上的触发输入。同时,Arduino向CAN总线[蓝线]发送一个 “0x201 报文”。

Memorator还可控制CAN2[橙色线]上的触发输出。它连接到Arduino,Arduino有一个内置上拉电阻器。

所有上述信号都连接到一个差分USB示波器。

如图所示,GPS[绿色]使用3.3V逻辑,Arduino生成5V负脉冲[红色]。

如果我们仔细观察,会发现当1PPS[绿色]变高时,触发[红色]将在大约16 μs后变低。大约140 μs后,我们可以看到Arduino通过MCP2515发出一个CAN报文[蓝色]。它的ID为0x201 (dec 513)。

本文未列出在Arduino上运行的程序。请发电邮至lgfr@kvaser.com,我会通过电邮发给你。

2通过t编程使用触发引脚

(你可在附录A – “Test_Memorator_Trigger_V100.t” 中找到t程序)

首先,我们需要一些常量和变量:

variables {
  int status = 0;

  // Memorator Pro
  const int MAX_CHANNELS = 2;
  const int DIGITAL_IN   = 0;
  const int DIGITAL_OUT  = 1;

  CanMessage Test_msg202;
  CanMessage Test_msg203;
}

我们定义初始化过程:

on start {
  int ch;
  printf("[START]\n");

  Test_msg202.id=0x202;//Dummy msg 202
  Test_msg202.dlc=0;
  Test_msg202.flags=0;
  Test_msg202.data="\x11\x22\x33\x44\x55\x66\x77\x88";
  
  Test_msg203.id=0x203;//Dummy msg 203 
  Test_msg203.dlc=1;
  Test_msg203.flags=0;
  Test_msg203.data="\x11\x22\x33\x44\x55\x66\x77\x88";


  status = kvIoPinSetInfo(0,kvIO_INFO_SET_DI_LOW_HIGH_FILTER,3000);
  status = kvIoPinSetInfo(0,kvIO_INFO_SET_DI_HIGH_LOW_FILTER,3000);

  status = kvIoConfirmConfig();
  if (status != 0) {
	printf("kvIoConfirmConfig failed: %d\n", status);
 }
  for (ch=0;ch < MAX_CHANNELS; ch++) {
	canBusOff(ch);
	canSetCommunicationMode(ch, canMODE_CAN);
	canSetBitrate(ch, canBITRATE_250K);
	canSetBusOutputControl(ch, canDRIVER_NORMAL);
	canBusOn(ch);
  }
}
不要忘记清理步骤:
on stop {
  int ch;
  printf("[STOP]\n");
  for (ch=0;ch < MAX_CHANNELS; ch++) {
	canBusOff(ch);
  }
}

不要忘记清理步骤:

on stop {
  int ch;
  printf("[STOP]\n");
  for (ch=0;ch < MAX_CHANNELS; ch++) {
	canBusOff(ch);
  }
}

让我们连接Memorator,并为测试总线启动t程序,看看会发生什么。

1PPS[绿色]每秒升高一次,
Arduino检测到它并降低触发[红色](大约需要35毫秒)。
Arduino还在CAN总线上发送 “报文201”。

可以理解,似乎没有什么特别的现象发生,因为我们只让Memorator连接总线,而我们还没做什么。

但代码中有一行很重要:
status = kvIoConfirmConfig();

在调用任何I/O函数之前,必须先调用此行。

添加一个 ON CANMESSAGE 钩子:

让我们加上这个钩子:

on CanMessage <0> 0x201
{
  canWrite(Test_msg202);
}

这个钩子的目的是显示Memorator在运行。当它看到一个 “201” 报文时,发送一个 “202” 报文。你可以在上图中看到这是第二个蓝色标记。

添加一些数字IO

on CanMessage <0> 0x201
{
  status = kvIoPinSetDigital(DIGITAL_OUT, 0);  
  canWrite(Test_msg202);
  status = kvIoPinSetDigital(DIGITAL_OUT, 1);  
}

使用命令“kvIoPinSetDigital(DIGITAL_OUT, 0);”,我们现在可以控制CAN2通道上的数字输出引脚。在上图中,我们可以看到,当发送 “202” 报文时,CAN2上的数字输出变低。

添加一个检测触发器的事件

on IoEvent <DIGITAL_IN> kvIO_EVENT_FALLING_EDGE {
  status = kvIoPinSetDigital(DIGITAL_OUT, 0);  
  canWrite(1,Test_msg203);
  status = kvIoPinSetDigital(DIGITAL_OUT, 1);  
}

这是一个新事件,IoEvent。它可以检测到下降沿。请注意,触发输入始终被定义为激活低电平。

每当Memorator检测到一个下降数字输入时,它将发送一个 “203报文”。我还添加了激活数字输出的说明。
在上图中,我们在约7毫秒后看到 “203报文”。(我已关闭了 “202报文”)。

7毫秒的响应时间是典型的响应时间吗?

让我们查看一下。

Memorator能多快检测到触发器?

当测试IoEvent时,很容易看到它在14到21毫秒内检测到触发器。它似乎在以预定义的模式运行。让我们测量一小时内的延迟:

在上图中,叠加了一个多小时的测量结果,我们可以看到延迟在3毫秒和11毫米之间均匀分布。

根据规范,触发脉冲必须为30 毫秒或更长(防抖检查),因此3到11毫秒的延迟时间对于所有正常操作都完全可以。

3 Summary总结

添加对Memorator的数字I/O通道的读和写支持 (TRIG IN 和 TRIG OUT) 非常简单。
我们只需要五个新步骤和一个新钩子:

kvIoPinSetInfo();
kvIoGetNumberOfPins();
kvIoConfirmConfig();
kvIoPinSetDigital();
kvIoPinGetDigital();

on IoEvent <DIGITAL_IN> kvIO_EVENT_FALLING_EDGE
数字IO的延迟约为3到11毫秒。
数字IO也可以通过CANlib控制;命令相同,只是CANlib不支持钩子。

如有任何问题或评论,请给我发电邮!

Field Application Engineer

Lars-Göran Fredriksson

LGFR@KVASER.COM

4 附录 A - “Test_Memorator_Trigger_V100.t”

variables {
  int status = 0;

  // Memorator Pro 2xHS
  const int MAX_CHANNELS = 2;
  const int DIGITAL_IN   = 0;
  const int DIGITAL_OUT  = 1;

  CanMessage Test_msg202;
  CanMessage Test_msg203;
}

on start {
  int ch;
  printf("[START]\n");

  //Dummy msg 202  
  Test_msg202.id=0x202;
  Test_msg202.dlc=0;
  Test_msg202.flags=0;
  Test_msg202.data="\x11\x22\x33\x44\x55\x66\x77\x88";

  //Dummy msg 203  
  Test_msg203.id=0x203;
  Test_msg203.dlc=0;
  Test_msg203.flags=0;
  Test_msg203.data="\x11\x22\x33\x44\x55\x66\x77\x88";

  int pinCount = 0;
  status = kvIoGetNumberOfPins(&pinCount);
  
  status = kvIoPinSetInfo(0,kvIO_INFO_SET_DI_LOW_HIGH_FILTER,3000 );
  status = kvIoPinSetInfo(0,kvIO_INFO_SET_DI_HIGH_LOW_FILTER,3000  );
  
  status = kvIoConfirmConfig();

  if (status != 0) {
    printf("kvIoConfirmConfig failed: %d\n", status);
 }

  for (ch=0;ch < MAX_CHANNELS; ch++) {
    canBusOff(ch);
    canSetCommunicationMode(ch, canMODE_CAN); 
    canSetBitrate(ch, canBITRATE_250K);
    canSetBusOutputControl(ch, canDRIVER_NORMAL);
    canBusOn(ch);
  }

  int value = 0;

  status = kvIoPinGetDigital(DIGITAL_IN, &value);

  status = kvIoPinSetDigital(DIGITAL_OUT, 1);  
}

on stop {
  int ch;
  printf("[STOP]\n");
  for (ch=0;ch < MAX_CHANNELS; ch++) {
    canBusOff(ch);
  }
  status = kvIoPinSetDigital(DIGITAL_OUT, 1);
  if (status == 0) {
    printf("Restored digital out\n");
  } else {
    printf("FAILED: %d\n", status);
  }
}

on IoEvent <DIGITAL_IN> kvIO_EVENT_FALLING_EDGE
{
  status = kvIoPinSetDigital(DIGITAL_OUT, 0);  
  canWrite(0,Test_msg203);
  status = kvIoPinSetDigital(DIGITAL_OUT, 1);  
}

5 附录 B GPS Signal Generator

如果你对源代码感兴趣,请给我发一封电子邮件,我会给你发一个链接。

Field Application Engineer

Lars-Göran Fredriksson

LGFR@KVASER.COM
Author Image

Prachi Patel

N/A