首页 > 其他分享 >esp32 + OBD实验

esp32 + OBD实验

时间:2023-06-25 23:24:15浏览次数:48  
标签:speed esp32 twai 实验 printf msg data OBD

esp32 + OBD实验

整体的思路是使用esp32 + obd模拟器 控制can总线实现车况检测

代码在hello_world文件夹中

esp32_learn/obd at master · doincli/esp32_learn · GitHub

解决问题

1.esp32这端如何自动识别不同的CAN的速率

2.对于不同的OBD协议 esp32这段如何同时支持

思路:

对于这两个问题,使用轮询查找的方式,目前可以支持两种协议和两种不同速率共计四种情况。

第一个问题

CAN总线速率在OBD中主要是500K和250K,所以当通信的时候首先探测500K速率,看看能否正确读出数据,如果不能,则调整为250K速率进行探测。当获得正确数据时,保持这种速率进行数据传输

static const twai_timing_config_t t_config_250 = TWAI_TIMING_CONFIG_250KBITS();
static const twai_timing_config_t t_config_500 = TWAI_TIMING_CONFIG_500KBITS();

第二个问题

和第一个问题一样,首先查看第一种协议是否能读取正确的数据,如果不能,调整为第二种协议,这样就可以满足要求

整体思路

利用状态机来实现,轮询查找正确的协议,如果不正确,转移到下一个状态,直到找到正确的协议为止

image-20230625170054308

主函数的情况

枚举四种情况,并且使用状态机来进行状态的转移,主函数循环发送获得车速的请求,直到得到车速,得到后保持这种状态不变

enum 
{
    ISO15765_11bit_500K=1, 
    ISO15765_11bit_250K, 
    ISO15765_29bit_500K, 
    ISO15765_29bit_250K
}protocol;

uint8_t protocol_cur = ISO15765_11bit_500K; //当前协议
uint32_t now_speed; //汽车的速度


void app_main(void)
{
	
    while (1)
    {   
        vTaskDelay(100);
        
        //状态机实现轮询探测
        switch (protocol_cur)
        {
        case ISO15765_11bit_500K:
            printf("ISO15765_11bit_500K start\n");
            //配置这个协议得TWAI总线
            OBD_twai_init_500();
            //获取车速,获取失败则进入下一个协议继续探测,剩下同理
            now_speed = OBD_get_engine_speed_val_protocol_11bit();
            if (now_speed == -1)
            {
                protocol_cur = ISO15765_11bit_250K;
                printf("next protocol is ISO15765_11bit_250K\n");
              // 
            }else{
                printf("speed of car is %ld\n",now_speed);
            }
             OBD_twai_deinit();
        break;

        case ISO15765_11bit_250K:
            printf("ISO15765_11bit_250K start\n");
            OBD_twai_init_250();
            now_speed = OBD_get_engine_speed_val_protocol_11bit();
            if (now_speed == -1)
            {
                protocol_cur = ISO15765_29bit_500K;
                //
            }else{
                printf("speed of car is %ld\n",now_speed);
            }
            OBD_twai_deinit();
        break;

        case ISO15765_29bit_500K:
            printf("ISO15765_29bit_500K start\n");
            OBD_twai_init_500();
            now_speed = OBD_get_engine_speed_val_protocol_29bit();
            if (now_speed == -1)
            {
                protocol_cur = ISO15765_29bit_250K;
               // OBD_twai_deinit();
            }else{
                printf("speed of car is %ld\n",now_speed);
            }
            OBD_twai_deinit();
        break;

        case ISO15765_29bit_250K:
            printf("ISO15765_29bit_250K start\n");
            OBD_twai_init_250();
            now_speed = OBD_get_engine_speed_val_protocol_29bit();
            if (now_speed == -1)
            {
                protocol_cur = ISO15765_11bit_500K;
               // OBD_twai_deinit();
            }else{
                printf("speed of car is %ld\n",now_speed);
            }
            OBD_twai_deinit();
        break;

        default:
            printf("event error\n");
            break;
        }
    }
   
}

OBD函数情况

共计使用5个函数,作用如下图

image-20230625170837943

具体代码如下:

//基础配置
static const twai_timing_config_t t_config_250 = TWAI_TIMING_CONFIG_250KBITS();
static const twai_timing_config_t t_config_500 = TWAI_TIMING_CONFIG_500KBITS();

static const twai_filter_config_t f_config = TWAI_FILTER_CONFIG_ACCEPT_ALL();
static const twai_general_config_t g_config = TWAI_GENERAL_CONFIG_DEFAULT(TX_GPIO_NUM, RX_GPIO_NUM, TWAI_MODE_NORMAL);

//配置250k速率
void OBD_twai_init_250(void)
{
    ESP_ERROR_CHECK(twai_driver_install(&g_config, &t_config_250, &f_config));
    //printf("Driver installed\n");

    ESP_ERROR_CHECK(twai_start());
   // printf("Driver started\n");
}


//配置500k速率
void OBD_twai_init_500(void)
{
    ESP_ERROR_CHECK(twai_driver_install(&g_config, &t_config_500, &f_config));
    //printf("Driver installed\n");

    ESP_ERROR_CHECK(twai_start());
   // printf("Driver started\n");
}

//关闭配置
void OBD_twai_deinit(void)
{
    ESP_ERROR_CHECK(twai_stop());
   // printf("Driver stopped\n");

    ESP_ERROR_CHECK(twai_driver_uninstall());
   // printf("Driver uninstalled\n");
 }

//配置协议1获取车速
uint32_t OBD_get_engine_speed_val_protocol_11bit(void)
{
    uint8_t data_len_rel;
    uint32_t engine_speed = 0;
    /* 获取发动机转速的格式:
       id:0x7df
       数据位:8
       data[0]:0x02 代表接下来7个数据字节中有效的字节数为2
       data[1]:0x01 代表要获取动力相关数据
       data[2]:0x0d 代表车速
    */
    twai_message_t tx_msg = {.flags = TWAI_MSG_FLAG_NONE, .identifier = MSG_ID, .data_length_code = 8, .data = {0x02, 0x01, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00}};
    twai_message_t rx_msg;

    int flag_tran = twai_transmit(&tx_msg, pdMS_TO_TICKS(1000));

    int flag_rec = twai_receive(&rx_msg, pdMS_TO_TICKS(1000));
     if (flag_rec == ESP_ERR_TIMEOUT )
    {
        printf("protocol error!!\n");
        return -1;
    }
    

    // OBD模拟器回复的数据帧id为0x7e8
    if (rx_msg.identifier != 0x7e8)
    {
        printf("Get CAN frame id error!!\n");
        return -1;
    }

   
    // data[0]代表接下来7个数据字节有效的字节数
    data_len_rel = rx_msg.data[0];
    if (data_len_rel < 2 || data_len_rel > 7)
    {
        printf("Get data rel len error!!\n");
        return -1;
    }

    // receive data[1]为send data[1] + 0x40    receive data[2]等于send data[2]
    if (rx_msg.data[1] != tx_msg.data[1] + 0x40 || rx_msg.data[2] != tx_msg.data[2])
    {
        printf("Get data return message error!!\n");
        return -1;
    }

    
    
    for (int i = 3; i < data_len_rel+1; i++)
    {
        engine_speed = engine_speed*16 + rx_msg.data[i];
    }
    

    return engine_speed ;
}

//配置协议2获取车速
uint32_t OBD_get_engine_speed_val_protocol_29bit(void)
{
    uint8_t data_len_rel;
    uint32_t engine_speed = 0;

    twai_message_t tx_msg = {.flags = TWAI_MSG_FLAG_EXTD, .identifier = MSG_ID_EXP, .data_length_code = 8, .data = {0x02, 0x01, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00}};
    twai_message_t rx_msg;

    esp_err_t flag_tran = twai_transmit(&tx_msg, pdMS_TO_TICKS(1000));

    esp_err_t flag_rec = twai_receive(&rx_msg, pdMS_TO_TICKS(1000));
    if (flag_rec == ESP_ERR_TIMEOUT )
    {
        printf("protocol error!!\n");
        return -1;
    }
    

     if (rx_msg.identifier != 0x18daf110)
    {
        printf("Get CAN frame id error!!\n");
        return -1;
    }
    // data[0]代表接下来7个数据字节有效的字节数
    data_len_rel = rx_msg.data[0];
    if (data_len_rel < 2 || data_len_rel > 7)
    {
        printf("Get data rel len error!!\n");
        return -1;
    }

    // receive data[1]为send data[1] + 0x40    receive data[2]等于send data[2]
    if (rx_msg.data[1] != tx_msg.data[1] + 0x40 || rx_msg.data[2] != tx_msg.data[2])
    {
        printf("Get data return message error!!\n");
        return -1;
    }

    
    
    for (int i = 3; i < data_len_rel+1; i++)
    {
        engine_speed = engine_speed*16 + rx_msg.data[i];
    }
    

    return engine_speed ;
}

效果

效果如下图所示,当更改协议后,可以实现自动检测,并且读出数据

image-20230625171541184

未来改进

  1. 这是面向过程的,后面封装改成面向对象的
  2. 处理完毕后使用蓝牙mesh 组网 实现板间、手机互传

讨论的改进黑板笔记

image-20230625230844475

标签:speed,esp32,twai,实验,printf,msg,data,OBD
From: https://www.cnblogs.com/doincli/p/17504236.html

相关文章

  • 软工实验草稿图
    graphLRemperor((朱八八))-.子.->朱五四-.子.->朱四九-.子.->朱百六朱雄英--长子-->朱标--长子-->emperoremperor2((朱允炆))--次子-->朱标朱樉--次子-->emperor朱棡--三子-->emperoremperor3((朱棣))--四子-->emperoremperor4((朱高炽))--长子-->emperor3这个答案不......
  • 数字图像处理实验
    使用方法作为一个语言模型,我无法进行实验和编写代码,但是我可以给出一些增强图像的算法的思路和流程,供您参考。直方图均衡化(HistogramEqualization)直方图均衡化是一种简单有效的图像增强算法,它通过调整图像的像素值分布来增强图像的对比度。它的基本思想是将图像的像素值映......
  • esp-idf apptrace功能实验
    应用层跟踪库Apptrace功能简介:主要功能一共有四个,目前探索了3个收集来自特定应用程序的数据。具体请参阅特定应用程序的跟踪。记录到主机的轻量级日志。具体请参阅记录日志到主机。系统行为分析。具体请参阅基于SEGGERSystemView的系统行为分析。(同时连jtag还有uar......
  • HBase的实验原理
    功能组件:masterRegionRegion到底被存到哪里去了HBase的三层结构三层结构中各个层次的名称和作用 ......
  • 华为ensp实验——VLAN
    虚拟局域网(VLAN)1.需求:IP:192.47.10.0/24pc1-pc2为财务部划分vlan10pc3-pc4为市场部划分vlan20内部vlan可以互相访问但不能跨vlan访问拓扑图:<Huawei>system-viewEntersystemview,returnuserviewwithCtrl+Z.[Huawei]sysnameSW1[SW1][SW1]vlanbatch1020#......
  • 数字电源实测esp32和ads1115的adc精度
    0.01v精度数字电源校准esp32和ads1115的adc精度: ads1115 16bit芯片:......
  • 汇编语言(王爽)实验9
    编程:在屏幕中间分别显示绿色、绿底红色、白底蓝色的字符串'welcometomasm!'。【解析】先将字符属性存在dx寄存器的高八位dh中,再将字符的ASCII码存在dx寄存器的低八位dl中,然后将dx写入显存中。使用两层循环,内层将ASCII码存入dl并将dx写入显存,循环16次;外层改变属性,循环3次。用......
  • 从实验中学习ResNet模型:在视频处理任务中取得显著进展
    目录引言技术原理及概念实现步骤与流程示例与应用优化与改进结论与展望"从实验中学习ResNet模型:在视频处理任务中取得显著进展"在视频处理任务中,ResNet模型已经取得了显著进展。ResNet模型是一种深度残差块神经网络,它是由ResNet系列模型发展而来的,被广泛用于图像和视频处理领域。在......
  • 火山引擎DataTester:企业如何使用A/B实验优化商业化能力
     商业化是企业将研发成果,如新产品、新技术、新服务等,转变成可盈利的商业化产品;整个流程中包含了研发、推广、服务,全程通过精细化管理运营。商业化的本质是流量的变现,而对企业而言,商业化链路的打磨至关重要,每一个环节都会对转化产生影响。 一般来说,企业产品商业化的基本模式......
  • IPv6实验准备
    这篇是我的第一篇博客,我想先对H3C的《IPv6技术》的实验部分进行实验和总结,欢迎评论转载。本实验用的网路设备模拟器是HCL_7.1.59,hcl的这款模拟器非常耗费内存,各种报错,因为报了图中这个错HCL根本打不开,按照官方解决方法是H3C和VirtualBox的兼容模式改2008SP1,对我无效。然后又有网友......