此博客中谈到的功能已在下列产品上进行了测试:
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 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不可能取代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
为了能够显示数字信号的表现,我必须有一个信号发生器以生成数字信号。我将使用示波器显示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,我会通过电邮发给你。
(你可在附录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毫秒的响应时间是典型的响应时间吗?
让我们查看一下。
当测试IoEvent时,很容易看到它在14到21毫秒内检测到触发器。它似乎在以预定义的模式运行。让我们测量一小时内的延迟:
在上图中,叠加了一个多小时的测量结果,我们可以看到延迟在3毫秒和11毫米之间均匀分布。
根据规范,触发脉冲必须为30 毫秒或更长(防抖检查),因此3到11毫秒的延迟时间对于所有正常操作都完全可以。
添加对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不支持钩子。
如有任何问题或评论,请给我发电邮!
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);
}
如果你对源代码感兴趣,请给我发一封电子邮件,我会给你发一个链接。