【ESP32 Arduino】【CAN通信】使用【ESP32CAN库】,对于CAN的消息进行滤波的程序

ESP32CAN的Examples对于esp32can_filter的程序注释非常少,非常的不明确,所以我广泛查找了各种资料,包括ESP IDF的和ST32的,终于搞懂了它的滤波逻辑,这里贴出我的程序,里面有详细的注释说明它的滤波逻辑

#ifdef U8X8_HAVE_HW_I2C
#include <Wire.h>
#endif
#ifdef U8X8_HAVE_HW_SPI
#include <SPI.h>
#endif

#include <ESP32CAN.h>
#include <CAN_config.h>
#include <Arduino.h>
#include <HuskyCANBoard2.h>

CAN_device_t CAN_cfg;               // CAN Config
const int rx_queue_size = 10;       // Receive Queue size

void setup() {
    Serial.begin(115200);
    Serial.println("Filter Demo - ESP32-Arduino-CAN");
    CAN_cfg.speed = CAN_SPEED_1000KBPS;//注意这里的通信速率,挂载在一条总线上的所有的设备必须一致,我开始一致没调出来就是因为这里设置错误了
    CAN_cfg.tx_pin_id = CAN_TX;
    CAN_cfg.rx_pin_id = CAN_RX;
    CAN_cfg.rx_queue = xQueueCreate(rx_queue_size, sizeof(CAN_frame_t));

    // Set CAN Filter
    // See in the SJA1000 Datasheet chapter "6.4.15 Acceptance filter"
    // and the APPLICATION NOTE AN97076 chapter "4.1.2 Acceptance Filter"
    // for PeliCAN Mode
    CAN_filter_t p_filter;//创建一个滤波器对象
    p_filter.FM = Single_Mode;//设置单滤波模式

    p_filter.ACR0 = 0x00;//验收代码寄存器 这个代表你想要过滤出的ID号
    p_filter.ACR1 = 0x20;//因为标准帧ID号的长度为11位,而这里的16进制有16位,所以你想要过滤出的ID号的值必须左移5位才是
    p_filter.ACR2 = 0x00;//16位的两个16进制数,以这里为例,我想要过滤出的ID号为1,所以1左移5位的10进制数为32,也就是0x20,所以这
    p_filter.ACR3 = 0x00;//里的ACR0为0x00,ACR1为0x20,再举个例子,比如我想过滤出ID号为1000的消息,则1000左移5位为的
    //10进制数3200016进制数为0x7D00,所以这里的ACR0为0x7D ACR1为0x00,

    p_filter.AMR0 = 0x00;//验收屏蔽寄存器 这里的 1 代表可以与上面规定的不同的位,0 代表必须严格相同的位
    p_filter.AMR1 = 0x0F;//这里我想严格的过滤出ID号为1的消息,所以这里的AMR0为0x00,代表前8位必须完全相同,
    p_filter.AMR2 = 0xFF;//AMR1为0x0F代表高4位必须完全相同,后四位无所谓,而AMR2和AMR3都为0xFF则表示后面的都可以不一样,也可以一样,不做要求
    p_filter.AMR3 = 0xFF;
    ESP32Can.CANConfigFilter(&p_filter);

    // Init CAN Module
    ESP32Can.CANInit();
}

void loop() {

    CAN_frame_t rx_frame;

    unsigned long currentMillis = millis();

    // Receive next CAN frame from queue
    if (xQueueReceive(CAN_cfg.rx_queue, &rx_frame, 3 * portTICK_PERIOD_MS) == pdTRUE) {

        if (rx_frame.FIR.B.FF == CAN_frame_std) {
            printf("New standard frame");
        } else {
            printf("New extended frame");
        }

        if (rx_frame.FIR.B.RTR == CAN_RTR) {
            printf(" RTR from 0x%08X, DLC %d\r\n", rx_frame.MsgID, rx_frame.FIR.B.DLC);
        } else {
            printf(" from 0x%08X, DLC %d, Data ", rx_frame.MsgID, rx_frame.FIR.B.DLC);
            for (int i = 0; i < rx_frame.FIR.B.DLC; i++) {
                printf("0x%02X ", rx_frame.data.u8[i]);
            }
            printf("\n");
        }
    }
}


  • 3
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 9
    评论
要实现对MAX30102红外(ir)数据进行小波滤波,可以按照以下步骤: 1. 获取MAX30102模块的ir数据。 2. 将ir数据存入一个数组中,并计算该数组的长度。 3. 选择适合的小波函数,比如haar小波、db小波等。 4. 将ir数据进行小波变换,得到小波系数。 5. 通过阈值去噪,将小波系数中的低幅值系数设置为0。 6. 将处理后的小波系数进行反变换,得到滤波后的ir数据。 下面是一个示例代码,可以在Arduino IDE中使用ESP32和MAX30102模块实现对ir数据进行小波滤波: ```c++ // 定义小波变换函数 void wavelet_transform(float *data, int len, int type) { // TODO: 实现小波变换算法 } // 定义小波反变换函数 void wavelet_inverse(float *coeffs, int len, int type) { // TODO: 实现小波反变换算法 } void setup() { // 初始化MAX30102模块 // ... // 定义数组存储ir数据 float ir_data[100]; int ir_len = 100; // 读取ir数据 for (int i = 0; i < ir_len; i++) { ir_data[i] = read_ir_data(); } // 进行小波变换 int wavelet_type = 1; // 使用haar小波 wavelet_transform(ir_data, ir_len, wavelet_type); // 阈值去噪 float threshold = 0.5; for (int i = 0; i < ir_len; i++) { if (abs(ir_data[i]) < threshold) { ir_data[i] = 0; } } // 进行小波反变换 wavelet_inverse(ir_data, ir_len, wavelet_type); // 输出滤波后的ir数据 for (int i = 0; i < ir_len; i++) { Serial.print(ir_data[i]); Serial.print(", "); } } void loop() { // ... } ``` 需要注意的是,小波变换算法的实现比较复杂,需要根据具体的小波函数进行计算。另外,阈值的选择也需要根据具体情况进行调整,以达到较好的滤波效果。
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Black__Jacket

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值