MC9S12G128开发板—解决小车九宫格方位移动功能实现遇到的一些问题

news2024/9/28 15:31:54

接着我的上一篇文章:MC9S12G128开发板—实现按键发送CAN报文指示小车移动功能。本篇文章主要记录下在实现小车九宫格方位移动功能过程中,遇到的一些程序问题以及解决措施。

1. 上位机小车响应开发板按键CAN报文指令的响应出错问题

问题现象描述

开发板上按KEY2键指示小车离开初始化的位置(0,0)即九宫格的左上角向下移动一格,但是发现小车向下先后移动了两次。

在这里插入图片描述

出错原因排查:程序关键位置添加打印,通过打印出来的下面截图中的三个列表可以判断出小车向下移动两次是通过小车需要移动位置列表curr_orient=[2,0]更新判断出来的。程序里面小车是否需要移动的逻辑判断是通过比较列表curr_orient与列表origin_orient的一致性,只要小车需要移动位置列表curr_orient与小车当前位置的列表origin_orient不一致,就执行列表curr_orient表示的方位的移动。

在这里插入图片描述

def analyse_orientation(data_str, origin_orient):
    data_list = data_str.split(" ")
    valid_data = data_list[:4]  # 前4字节表示方位的报文信息
    if "01" in valid_data:
        idx = valid_data.index("01")
        orient = orient_dict[idx]
        if orient == "上":
            curr_orient = [origin_orient[0] - 1, origin_orient[1]]
        elif orient == "下":
            curr_orient = [origin_orient[0] + 1, origin_orient[1]]
        elif orient == "左":
            curr_orient = [origin_orient[0], origin_orient[1] - 1]
        elif orient == "右":
            curr_orient = [origin_orient[0], origin_orient[1] + 1]
        else:
            raise Exception("无效的方位")
        # 判断更新的方位是否有效
        if check_orient(origin_orient, curr_orient):
            return curr_orient
        else:
            return origin_orient
    else:
        return origin_orient
def check_orient(origin_orient, curr_orient):
    if (curr_orient[0] < 0) or (curr_orient[1] < 0):
        return False
    elif (curr_orient[0] > 2) or (curr_orient[1] > 2):
        return False
    elif (origin_orient[0]) == curr_orient[0] and (origin_orient[1] == curr_orient[1]):
        return False
    else:
        return True

经分析主要是开发板按键一次发送向下移动报文后,会一直发送该条报文,导致小车会一直执行向下移动的指令。修改开发板程序后,上位机程序能够按照原逻辑正确解析报文指示小车移动。

在这里插入图片描述

2. 上位机小车响应一帧指示移动方位的报文存在延时响应或者响应不及时的问题

由于出现了问题1:上位机小车响应开发板按键CAN报文指令的响应出错问题,调整了开发板的程序每次只会发送一帧指示方位更新的报文,会导致上位机程序在接收处理报文信息时存在延时响应或者响应不及时的问题。

分析程序发现,目前造成信息不同步的原因主要是写入报文数据和读取报文数据判断方位的逻辑是不同线程控制的,两个线程之间存在信息不同步的问题。暂时可以通过以下方式解决该问题:设置读取报文数据判断方位的线程中run()方法执行1秒钟的延时。

    def run(self):
        while not self.stop_flag:
            # 按“开始”按钮进入小车方位移动线程后,重新读取报文存储文件,通过最后一条报文判断小车应该前进的方位
            msg_data = self.read_msg_fromtext()
            curr_orient = analysis_msg.analyse_orientation(msg_data, self.origin_orient)
            if curr_orient != self.origin_orient:
                self.update_bitmap(curr_orient).SetBitmap(wx.Bitmap(self.img))
                # time.sleep(5)
                time.sleep(1)
            self.origin_orient = curr_orient

3. CAN通信连接-断开-连接过程中,上位机界面显示接收到的报文帧序号出错

出错现象截图如下:

在这里插入图片描述

从上图可以看出,断开CAN通信后,接收到的报文帧序号后三位有的是从001开始依次增加1的,有的报文帧序号从断开CAN通信前的最后一帧报文序号384依次增加1的。

出错原因排查:分析程序代码,出错原因在于鼠标点击“断开”按钮后,程序执行关闭CAN通信的线程但是没有中断CAN通信接收报文的线程,重新点击“连接”按钮启动CAN通信接收报文的线程,导致存在先后两个CAN通信接收报文的线程执行。

使用知乎https://www.zhihu.com/question/595940230?utm_id=0上的Python中断线程方法成功解决了该问题,Python线程中断方法如下:

在这里插入图片描述

增加“断开”CAN通信中断CAN报文接收线程功能后,上位机界面成功运行的截图如下:

在这里插入图片描述

4. 关闭上位机界面,程序未响应,界面卡死

在这里插入图片描述

经分析发现是程序处理逻辑问题:只是按照上述问题3:CAN通信连接-断开-连接过程中,上位机界面显示接收到的报文帧序号出错,通过设置标志位的方式中止了线程中循环的执行,并没有堵塞线程,应该通过join()方式堵塞线程的执行使线程执行完成后正常退出。

        # 窗口关闭事件
        self.Bind(wx.EVT_CLOSE, self.exit_sys)
    def exit_sys(self, event):
        try:
            # 先强制结束报文接收线程
            self.link_thread.stop()
            self.link_thread.join()
            self.click_thread.stop()
            self.click_thread.join()
            if self.MyPanel1.m_button1.GetLabel() == "断开":  # 表示处于CAN通信连接的状态
                self.close_link()
        except AttributeError:
            pass
        # 清空报文记录文件receive_msg.txt
        open("receive_msg.txt", 'w').close()
        self.Destroy()
        sys.exit(1)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/487106.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

自动驾驶行业观察之2023上海车展-----车企发展趋势(1)

新势力发展趋势 小鹏汽车&#xff1a;发布新车G6&#xff08;中型SUV&#xff09;&#xff0c;将于2023年年中上市 发布新车G6&#xff1a;车展上&#xff0c;小鹏G6正式首发亮相&#xff0c;定位中型SUV&#xff0c;对标Tesla Model Y&#xff0c;将于2023年年中上市并开始交…

基于web的商场商城后台管理系统

该系统用户分为两类&#xff1a;普通员工和管理员。普通员工是指当前系统中的需要对商品和客户的信息进行查询的人。此类用户只能查看自己的信息&#xff0c;以及对商品和客户的信息进行查看。管理员用户可以对自己和他人的信息进行维护&#xff0c;包括对商品入库、销售、库存…

Redis缓存过期淘汰策略

文章目录 1、如何设置 Redis 最大运行内存&#xff1f;2、过期删除策略3、内存淘汰策略 1、如何设置 Redis 最大运行内存&#xff1f; 在配置文件 redis.conf 中&#xff0c;可以通过参数 maxmemory 来设定最大运行内存&#xff0c;只有在 Redis 的运行内存达到了我们设置的最…

代码命名规范

日常编码中&#xff0c;代码的命名是个大的学问。能快速的看懂开源软件的代码结构和意图&#xff0c;也是一项必备的能力。那它们有什么规律呢&#xff1f; Java项目的代码结构&#xff0c;能够体现它的设计理念。Java采用长命名的方式来规范类的命名&#xff0c;能够自己表达…

消息称苹果Type-C口充电未设MFi限制,iOS17将更新Find My服务

根据国外科技媒体 iMore 报道&#xff0c;基于消息源 analyst941 透露的信息&#xff0c;苹果公司目前并未开发 MFi 限制。 根据推文信息内容&#xff0c;两款 iPhone 15 机型的最高充电功率为 20W&#xff0c;而 iPhone 15 Pro 机型的最高支持 27W 充电。 此前古尔曼表示苹…

Python趋势外推预测模型实验完整版

趋势外推预测模型实验完整版 实验目的 通过趋势外推预测模型&#xff08;佩尔预测模型&#xff09;&#xff0c;掌握预测模型的建立和应用方法&#xff0c;了解趋势外推预测模型&#xff08;佩尔预测模型&#xff09;的基本原理 实验内容 趋势外推预测模型 实验步骤和过程…

第4章-虚拟机栈(多使用到jclasslib工具查看字节码)

虚拟机栈 简介 虚拟机栈的出现背景 由于跨平台性的设计&#xff0c;Java的指令都是根据栈来设计的。不同平台CPU架构不同&#xff0c;所以不能设计为基于寄存器的【如果设计成基于寄存器的&#xff0c;耦合度高&#xff0c;性能会有所提升&#xff0c;因为可以对具体的CPU架…

警惕免杀版Gh0st木马!

https://github.com/SecurityNo1/Gh0st2023 经过调查发现&#xff0c;这款开源的高度免杀版Gh0st木马目前正在大范围传播&#xff0c;据称可免杀多种主流杀软&#xff1a;开发者不仅制作了新颖的下载页面&#xff0c;还设法增加了搜索引擎的收录权重&#xff0c;吸引了许多免…

Python基础合集 练习17(类与对象)

class Dog: pass papiDog() print(papi) print(type(papi)) 构建方法 创建类过后可以定义一个特殊的方法。在python中构建方法是__init__(),init()必须包含一个self参数 class pig(): #def__init__(self) -> None&#xff1a; print(‘你好’) pipgpig() 属性和方法 cl…

JDBC详解(六):数据库事务(超详解)

JDBC详解&#xff08;六&#xff09;&#xff1a;数据库事务&#xff08;超详解&#xff09; 前言一、数据库事务介绍二、JDBC事务处理三、事务的ACID属性1、数据库的并发问题2、四种隔离级别3、在MySql中设置隔离级别 前言 本博主将用CSDN记录软件开发求学之路上亲身所得与所…

MySQL基础——数据模型·数据库操作

♥️作者&#xff1a;小刘在C站 ♥️个人主页&#xff1a;小刘主页 ♥️每天分享云计算网络运维课堂笔记&#xff0c;努力不一定有收获&#xff0c;但一定会有收获加油&#xff01;一起努力&#xff0c;共赴美好人生&#xff01; ♥️树高千尺&#xff0c;落叶归根人生不易&…

开放原子训练营(第一季)铜锁探密:基于铜锁,在前端对登录密码进行加密,实现隐私数据保密性

本文将基于 铜锁&#xff08;tongsuo&#xff09;开源基础密码库实现前端对用户登录密码的加密&#xff0c;从而实现前端隐私数据的保密性。 首先&#xff0c;铜锁密码库是一个提供现代密码学算法和安全通信协议的开源基础密码库&#xff0c;在中国商用密码算法&#xff0c;例…

vcruntime140_1.dll无法继续执行代码怎么修复

vcruntime140_1.dll 是 Microsoft Visual C 程序集中的一个动态链接库文件。该文件提供了一些 C 运行时函数&#xff0c;这些函数是由许多应用程序使用的。当一个程序需要某个 DLL 文件时&#xff0c;它会首先在系统目录和程序所在目录中查找该 DLL 文件。如果系统或程序目录中…

《密码法》

第一章 总 则 第一条 为了规范密码应用和管理&#xff0c;促进密码事业发展&#xff0c;保障网络与信息安全&#xff0c;维护国家安全和社会公共利益&#xff0c;保护公民、法人和其他组织的合法权益&#xff0c;制定本法。 第二条 本法所称密码&#xff0c;是指采用特定变…

JavaSE基础(三)—— 程序流程控制、Random随机数

目录 一、顺序结构 二、分支结构 1. if 1.1 if分支有三种格式​编辑 2. switch 2.1 if、switch分支各自适合做什么业务场景 3. switch的穿透性 三、循环结构 1. for 循环​编辑 2. while 循环 2.1 什么时候用for循环&#xff0c;什么时候用while循环 3. do-while循…

探索抖音全域兴趣电商的特点与优势

抖音全域兴趣电商是抖音在电商领域的一项创新业务。它是一种全新的购物方式&#xff0c;通过抖音平台提供的社交化购物体验&#xff0c;将用户的兴趣、购物需求和商品展示相结合&#xff0c;为用户提供更为个性化、精准的购物体验。下面四川不若与众将对抖音全域兴趣电商进行一…

uboot start_armboot函数 第二阶段代码分析

1.1、start_armboot函数简介 这个函数整个构成了uboot启动的第二阶段。 1.2、uboot第二阶段做的事情 uboot第一阶段主要就是初始化了SoC内部的一些部件&#xff08;譬如看门狗、时钟、串口…&#xff09;&#xff0c;然后初始化DDR并且完成重定位。那么&#xff0c;uboot的第…

Win10配置ESP32-IDF+VSCode开发环境

一、安装包下载&#xff1a; Git&#xff1a;Git for WindowsPython&#xff1a;Download Python | Python.org以Windows x86-64开头的是 64 位的 Python 安装程序&#xff1b;以Windows x86开头的是 32 位的 Python 安装程序。ESP-IDF&#xff08;选择Offline版本&#xff09…

【微机原理】8088/8086的寻址方式

目录 一.指令的组成 二.操作数的寻址方式 1.立即数寻址 2.寄存器寻址方式 3.存储器寻址方式 &#xff08;1&#xff09;直接寻址 &#xff08;2&#xff09;寄存器间接寻址 &#xff08;3&#xff09;寄存器相对寻址方式 &#xff08;4&#xff09;基址变址寻址方式&#xff08…

基于zookeeper实现分布式锁

目录 zookeeper知识点复习 相关概念 java客户端操作 实现思路分析 基本实现 初始化链接 代码落地 优化&#xff1a;性能优化 实现阻塞锁 监听实现阻塞锁 优化&#xff1a;可重入锁 zk分布式锁小结 zookeeper知识点复习 Zookeeper&#xff08;业界简称zk&#xff…