M5Stack的CAN BUS通讯-Arduino中文社区 - Powered by Discuz! Archiver

vany5921 发表于 2020-8-14 11:31

M5Stack的CAN BUS通讯

本帖最后由 vany5921 于 2020-8-14 11:35 编辑

      尝试使用MCP2515使用CAN BUS模块发送和接收以M5Stack Gray内置的IMU数据。CAN(控制器局域网)是一种用于汽车的具有高抗噪性的通信标准。 CAN BUS模块的布线速度最高为1 Mbps,仅需要两条电缆CANH / CANL,因此我认为它实际上很容易用于业余爱好。这次,我尝试使用内置的IMU在CAN上发送和接收带有相对大量信息的数据。

构成:

[*]M5Stack Gray(IMU消息发送)
[*]CAN BUS模块1CAN BUS模块2Arduino MegaPC(Processing可视化)
对于CAN BUS模块,我使用了在亚马逊上经常看到的两个模块。MCP2515用于CAN控制器,TJA1050用于CAN收发器,并且可以通过SPI与微型计算机连接。 CAN 120Ω终端电阻也可以通过跳线启用。如上所述,所购买的产品配备有8MHz的晶体振荡器。 只要此处的设置正确,就可以与其他CAN BUS模块通信。

M5Stack(发送方)和CAN BUS模块
如下所示进行SPI连接

由于M5Stack的SPI为3.3V类型,因此3.3V也提供给CAN BUS模块。 另外,这次仅从M5Stack侧进行传输,因此没有任何东西连接到INT。 顺便说一句,CS只需要一个数字引脚,但是它将被限制为一个引脚选项,可以通过使用内置LCD和IMU在不产生扬声器大声噪声的情况下使用它。顺便说一句,不要使用不可靠的杜邦线(我在这里花了一个小时)。
Arduino Mega(接收器)和CAN BUS模块
如下所示进行SPI连接

我偶然遇到了一个Arduino Mega,因此尝试使用它,但是我认为Uno没问题(尽管SPI连接发生了变化)。 发送端的M5Stack没有建立INT连接,但是在接收端,它与中断兼容引脚相连。 这是为了在PC端启用中断接收。

程序
CAN_BUS_Shield库用于CAN BUS模块控制程序,M5Stack MPU9250示例用于M5Stack侧IMU控制程序,该程序直接用于处理。

1.M5Stack侧程序
这是M5Stack示例程序(MPU9250BasicAHRS.ino)所做修改的摘录。在此程序中,将从IMU(MPU9250)获取的四元数的4个元素(浮点数)赋予不同的ID,并与时间戳一起发送到CAN。 我不确定该方法是否正确,但是暂时将其作为对向CAN高速数据传输的测试。

#define CAN_OUT
/*CAN settings*/
#include <mcp_can.h>
const int SPI_CS_PIN = 5;
MCP_CAN CAN(SPI_CS_PIN);
unsigned char stmp = {0, 0, 0, 0, 0, 0, 0, 0};加载<mcp_can.h>, 不要忘记安装CAN_BUS_Shield库。使用SPI_CS_PIN配置用于SPI器件选择的数字引脚。 在M5Stack的情况下,由于许多引脚与LCD和扬声器等内置设备共享,因此,如果您选择错误,LCD将无法工作或扬声器会发出很大的噪音,这很奇怪。
在stmp 上准备了用于发送到CAN的消息缓冲区。* CAN规范的结构为id 11位和数据64位(8字节)。

void sendCanMsgFloat(unsigned long id, unsigned long timestamp, float val){
   union {
             float f;
             unsigned char b;
   } ftob;
ftob.f = val;
union {
            unsigned long l;
            unsigned char b;
} ultob;
ultob.l = timestamp;

stmp = ultob.b;
stmp = ultob.b;
stmp = ultob.b;
stmp = ultob.b;   
stmp = ftob.b;
stmp = ftob.b;
stmp = ftob.b;
stmp = ftob.b;

CAN.sendMsgBuf(id, 0, 8, stmp);
delay(2);
}该功能实际上是将数据发送到CAN的功能。 一种数据结构用于将float和unsigned long(假设时间戳记)转换为字节格式。 由于在Arduino上均为32位,因此发送到CAN的数据总计为64位。在字节顺序方面,我更改了顺序,因为Arduino的字节序为Little Endian,而CAN BUS的字节序为Big Endian(网络字节序)。

#ifdef CAN_OUT
while (CAN_OK != CAN.begin(CAN_500KBPS, MCP_8MHz)) {         // init can bus : baudrate = 500k
   Serial.println("CAN BUS Shield init fail");
   Serial.println(" Init CAN BUS Shield again");
   delay(100);
}
Serial.println("CAN BUS Shield init ok!");
#endif //CAN OUTPUT初始化CAN设备。 根据要连接的CAN模块的工作频率设置MCP_8MHz部分。 似乎可以在CAN_BUS_Shield库中选择MCP_16MHz。 此部分中的设置不正确将阻止与其他CAN设备的正常通信。 (在8MHz的情况下,我认为很难进行1Mbps的CAN通信。)CAN_500KBPS部分定义了CAN BUS通信速度。

M5.Lcd.setCursor(0,120);
M5.Lcd.printf("q0:% 5.2f qx:% 5.2f qy:% 5.2f qz:% 5.2f \r\n",(*getQ()), (*(getQ() + 1)), (*(getQ() + 2)), (*(getQ() + 3)));//print quaternion我试图在M5Stack的LCD上显示四元数。
#ifdef CAN_OUT
    sendCanMsgFloat(0x01, IMU.count, *getQ());
    sendCanMsgFloat(0x02, IMU.count, *(getQ() + 1));
    sendCanMsgFloat(0x03, IMU.count, *(getQ() + 2));
    sendCanMsgFloat(0x04, IMU.count, *(getQ() + 3));
#endif使用上述功能,将四元数的每个元素发送给具有不同ID和时间戳的CAN。
打开用opendiff软件,对比修改后的文件。



Arduino Mega程序
Arduino Mega端对从CAN BUS获取的M5Stack IMU数据进行解码,并通过串行通信将其中继到正在处理的查看器。 CAN_BUS_Shield库示例程序receive_check.ino用于CAN的接收部分。

/*for processing*/
uint8_t teapotPacket = { '此功能将解码的IMU四元数信息转换为处理程序可以使用的格式。 我已经在本文中使用过一个。
//SERIAL.println("-----------------------------");
//SERIAL.print("Get data from ID: 0x");
//SERIAL.println(canId, HEX);

//for (int i = 0; i < len; i++) { // print the data
//    SERIAL.print(buf, HEX);
//    SERIAL.print("\t");
//}
union {
   float f;
   unsigned char b;
} ftob;
if(canId == 1){
   ftob.b = buf;
   ftob.b = buf;
   ftob.b = buf;
   ftob.b = buf;
   q0 = ftob.f;
}else if(canId == 2){
   ftob.b = buf;
   ftob.b = buf;
   ftob.b = buf;
   ftob.b = buf;
   q1 = ftob.f;
}else if(canId == 3){
   ftob.b = buf;
   ftob.b = buf;
   ftob.b = buf;
   ftob.b = buf;
   q2 = ftob.f;
}else if(canId == 4){
   ftob.b = buf;
   ftob.b = buf;
   ftob.b = buf;
   ftob.b = buf;
   q3 = ftob.f;从CAN设备接收到的数据被解码并变成四元数的四个元素。再次,用opendiff复制代码进行对比。




PC端程序
在处理中按原样照搬MPUTeapot.pde 不要指定串行端口。
您会看到M5Stack的物理运动与“Processing”中显示的飞机一起运动。


, 0x02, 0,0, 0,0, 0,0, 0,0, 0x00, 0x00, '\r', '\n' };
int qw, qx, qy, qz;
float q0, q1, q2, q3;

void printProcessing(){
   qw =int(q0 * 16384.0f);
   qx =int(q1 * 16384.0f);
   qy =int(q2 * 16384.0f);
   qz =int(q3 * 16384.0f);

   teapotPacket = highByte(qw);
   teapotPacket = lowByte(qw);
   teapotPacket = highByte(qx);
   teapotPacket = lowByte(qx);
   teapotPacket = highByte(qy);
   teapotPacket = lowByte(qy);
   teapotPacket = highByte(qz);
   teapotPacket = lowByte(qz);
   SERIAL.write(teapotPacket, 14);
   teapotPacket++; // packetCount, loops at 0xFF on purpose
}此功能将解码的IMU四元数信息转换为处理程序可以使用的格式。 我已经在本文中使用过一个。
&nbsp;//SERIAL.println("-----------------------------");
&nbsp;//SERIAL.print("Get data from ID: 0x");
&nbsp;//SERIAL.println(canId, HEX);

&nbsp;//for (int i = 0; i &lt; len; i++) { // print the data
&nbsp;//    SERIAL.print(buf, HEX);
&nbsp;//    SERIAL.print("\t");
&nbsp;//}
&nbsp;union {
&nbsp; &nbsp; &nbsp;float f;
&nbsp; &nbsp; &nbsp;unsigned char b;
&nbsp;} ftob;
&nbsp;if(canId == 1){
&nbsp; &nbsp; &nbsp;ftob.b = b &nbsp;uf;
&nbsp; &nbsp; &nbsp;ftob.b = buf;
&nbsp; &nbsp; &nbsp;ftob.b = buf;
&nbsp; &nbsp; &nbsp;ftob.b = buf;
&nbsp; &nbsp; &nbsp;q0 = ftob.f;
&nbsp;}else if(canId == 2){
&nbsp; &nbsp; &nbsp;ftob.b = buf;
&nbsp; &nbsp; &nbsp;ftob.b = buf;
&nbsp; &nbsp; &nbsp;ftob.b = buf;
&nbsp; &nbsp; &nbsp;ftob.b = buf;
&nbsp; &nbsp; &nbsp;q1 = ftob.f;
&nbsp;}else if(canId == 3){
&nbsp; &nbsp; &nbsp;ftob.b = buf;
&nbsp; &nbsp; &nbsp;ftob.b = buf;
&nbsp; &nbsp; &nbsp;ftob.b = buf;
&nbsp; &nbsp; &nbsp;ftob.b = buf;
&nbsp; &nbsp; &nbsp;q2 = ftob.f;
&nbsp;}else if(canId == 4){
&nbsp; &nbsp; &nbsp;ftob.b = buf;
&nbsp; &nbsp; &nbsp;ftob.b = buf;
&nbsp; &nbsp; &nbsp;ftob.b = buf;
&nbsp; &nbsp; &nbsp;ftob.b = buf;
&nbsp; &nbsp; &nbsp;q3 = ftob.f;从CAN设备接收到的数据被解码并变成四元数的四个元素。再次,用opendiff复制代码进行对比。




PC端程序
在处理中按原样照搬MPUTeapot.pde 不要指定串行端口。
您会看到M5Stack的物理运动与“Processing”中显示的飞机一起运动。


liaoze22 发表于 2020-12-25 17:51

感谢分享,做的不错!
页: [1]
查看完整版本: M5Stack的CAN BUS通讯