关于电子设计大赛无人机题的学习笔记(3)常用设备总线的使用方法(IIC)

关于电子设计大赛无人机题的学习笔记(3)常用设备设备总线的使用方法(IIC)

)

1. 吐槽及日志

首先 电赛因为疫情原因推迟了 ,emmm在我看来跟取消了差不了太多,这一波小系列的学习记录暂时只能在第三篇就停止更新了,之后会写一整个系列的飞控方法和分析的文章,三号得知这个消息到现在人都处于一种比较浑浑噩噩的状态,尽管知道这是十分不好的状态但是我还是很难去扭转这种现实,因为之前已经完全进入备赛状态的身心紧绷的状态已经垮掉了。昨天2021 8.8 去参加了DJI办的青年工程师大会 ,见到了一些以前合作过的战友,才让我稍微好转了一点,但是还是觉得身心压力很大,不过这次是正面刺激,我觉得我能做的更好一点,因为我看到我能做更多的可能性,之后我的研究重心会转移到多机器人协同算法,还有多机编队飞行控制系统的设计上。目前看起来状态正在慢慢好转,实验室的结构基本也成型了,Falcon_Swarm_Robotic_LAB 以后会算是正式在这间实验室展开工作了。希望一切顺利。

2.设备总线

  • 总线是嵌入式领域必须掌握的通信方式,嵌入式设备缺少了它就好像人类缺少了交流能力不能说话,也不能听见,更不能分享想法 在机器和传感器,控制单元之间各自完成了自己的工作后要分享结果,那么久需要总线来进行沟通
  • 常见的总线包括 UART,IIC,ISP,CAN。这些总线十分有年代但是如今还是非常通用,甚至像CAN总线,在未来的未来可以预期它仍然是汽车行业的必要总线,很难找到更好的解决方案
  • 总线的分类大致包括按三中类型进行区分,第一种区分方式:按功能可以分为 地址总线,数据总线,控制总线
  • 按传输方法分类:可以分为串行总线和并行总线:区别是能否一次允许多机之间的总线互通,类似于只有一条跑道让数据跑步和好多条跑道让数据跑步的区别,但是相应的成本必然会有所增加。
  • 按时钟信号方式分类:可以分为同步总线和异步总线:同步和异步的主要区别在于其数据是否需要一条独立的时钟线进行支撑

3.IIC

今天主要讨论的是在电赛过程中我所主要负责研究的模块:HWT906 惯性测量单元,这款传感器的数据即是通过IIC总线进行收发。
IIC总线的特殊之处在于其有MASTER和SLAVE两种机制,主机可以发出指令,好的现在从机一二三给我数据,我给你数据,四五六关闭别说话。但是反过来却是不行的,在从机想像主机申请数据的时候是不被认可的

IIC总线的主要架构

在这里插入图片描述
IIC总线主要由两条时钟线构成:SDA和SCL其中在设备端必须加一个上拉电阻链接到正的电源电压,才能够正常运行,即两条线路必须在空闲时都保持高电压的模式。且连接到总线的器件输出级必须是漏极开路或集电极开路才能执行线与的功能。

IIC的位传输

在这里插入图片描述
IIC总线的数据流模型

IIC接口的通讯方式研究

IIC的通信过程在第一层可以分为

初始化init,发送,读取

展开来分析

首先要提到的IIC的时序线中必须包括ACK数据头或是NACK数据头,这两种数据头包装方式包含了不同的电平变换信息

以及每一次数据的开始一定会包含START头和STOP电平

IIC的init比较简单

启动对应SCL的引脚。

IIC的数据发送

IIC的数据Send和Write是两种相关联的数据传输方式

Write是正式的写入方法方法

  • 写入的时序是
void I2C_Write_Byte_HWT(uint8_t Slaveaddr, uint8_t REG_Address, uint8_t *REG_data)
{
    
    
    IIC_Start();
    IIC_SendByte(Slaveaddr);
		
    IIC_RecvACK();
 		delay(10);
    IIC_SendByte(REG_Address);
		IIC_RecvACK();
		delay(10);
    IIC_SendByte(REG_data[0]);
    IIC_RecvACK();
		delay(10);
		IIC_SendByte(REG_data[1]);
		IIC_RecvACK();
		delay(10);
    IIC_Stop();
}
void I2C_Write_Byte(uint8_t Slaveaddr, uint8_t REG_Address, uint8_t REG_data)
{
    
    
    IIC_Start();
    IIC_SendByte(Slaveaddr);
    IIC_RecvACK();
    IIC_SendByte(REG_Address);
    IIC_RecvACK();
    IIC_SendByte(REG_data);
    IIC_RecvACK();
    IIC_Stop();
}

  • START -->ACK–>SEND_ADDRESS–>ACK->SEND_REG–>…–>ACK–>STOP
  • 读取的时序是
uint8_t I2C_Read_Bytes(uint8_t Slaveaddr, uint8_t REG_Address, uint8_t *ptr, uint8_t len)
{
    
    
    IIC_Start();
    IIC_SendByte(Slaveaddr);
    IIC_RecvACK();
		delay(10);
    IIC_SendByte(REG_Address);
    IIC_RecvACK();
		delay(10);
    IIC_Start();
    IIC_SendByte(Slaveaddr + 1);
    IIC_RecvACK();
    while (len)
    {
    
    
				delay(10);delay(10);				//这个地方的时序决定了所有的事情
        if (len == 1)
        {
    
    
            *ptr = IIC_RecvByte();
						
            IIC_SendACK(0);
        }
        else
        {
    
    
            *ptr = IIC_RecvByte();
						
            IIC_SendACK(1);
        }
        ptr++;
        len--;
    }
    IIC_Stop();
    return 0;
}
  • START–》ACK–》SEND_ADDRESS–>ACK–>SEND_REG–>START–>SEND–>ADDRESS+1–>READ_ONE_bete–>ACK–>READ_ONE_bete–>ACK–>NACK–>STOP

开发过程的一些吐槽和经验

在开发过程中,IIC的通讯协议时序是十分重要的部分,如果其时序分配不正确那么将不能正常的收发数据 ,哪怕只是轻微的数据帧重叠都会导致故障和问题

IIC的读取时序较为简单,写入的方法较为复杂。

ACK可以理解为应答机信号,即SLAVE打出信号后如果电平的到了翻转但是在并非自己改回电平的情况下电平发生了改变那么ACK电平正确应答,在时序中可以看到ACK电平信息。

结合程序已有框架进行传感器更换的实现思路

更换传感器本就是十分冒险的操作,目前已有的飞机的自身传感器虽然已经比较完善,但是飞机的飞行状态并不十分平稳,而且通过在飞行状态和LOCK状态下的DEBUG调试情况并且通过JTAG通过示波器读取了MPU6050的数据解析波形,可以观测到波形的状态毛刺,突变相当的严重,关于这些问题联系到飞机上为了降低成本选用了自制的MPU6050传感器就可以解释这些情况了

这也就引出了我们更换传感器的必要性,传感器HWT906在进行新传感器选型时进入了我们的视野,这一款传感器有完善的数据手册和各种资料以及厂家的完善支持,除此以外,它是一款高精度的IMU这是对我们的研究带来非常好的支持的事情,尽管更换核心传感器的想法十分危险,但是这是值得尝试的。

在前期经过大量的考虑,基本读懂FUM基本框架的前提下,决定尽量封装HWT906的数据,将HWT906的数据封装成和MPU6050的数据结构封装成完全一样的部分,在进行校验后如果两者的误差在10%以内,就选择HWT906的数据替换掉MPU6050的数据,将数据进行精确,但是在后续遇到了其他问题。

根据可能发生的问题做出的预判

可能遇到的问题在开始实验和开发之初就已经有了一部分考虑

最大的问题是传感器如果跟换失败,那么飞行器一定会出现飞行姿态故障,飞行器会出现危险行为动作,为此首先加了强制控制环,如果程序的原始IMU发生危险动作反馈,直接锁死所有桨叶确保不会有更大的危险,

其他的一些问题包括了跟换的元素是否能保证数据正确性,在后期的测试中确实出现了这方面的问题,最后我们决定加入帧首尾测试确保数据帧的正常,能否保证数据的单位是符合MPU6050的数据单位的,在测试后数据比较符合,所以认为其符合

在开始调试后使用别人开源代码做的方案失败

原因分析

这套代码的波特率与所选的新型传感器HWT906IMU并不适配,并且在更换了两端到一致的波特率后还是不能够正确识别数据,更可能的原因是传感器的设置有问题或者是主从机的通信关系有问题,这是非常致命的,仔细查找代码后发现这套开源的IIC框架对于未能出现的上拉电阻并没有进行处理,更加巧合的是这款传感器的核心部分的确没有上拉电阻,解决了第一个问题,此时双端通信得到了实现,但是收到的数据和地址寄存器的控制位发回的信息仍然是失控的状态,0xFFFF现在看到这一串就头大,好的只能进行数据分析了

数据流分析

在数据流分析的环节,使用逻辑分析仪,直接观测了两个引脚所输出的时钟信号组合完成的数据信息,这些信息是能够被完整观测的,在观测后发现,每一位数据位和ACK应答机都发生了重叠,由此导致了乱码的产生,并且地址位是错误的,经过查询技术手册发现传感器的地址位必须左移一位才能够正确进行读取寄存器的值,在对这个问题修正后,再次修改开源代码在每一位数据位发送完后加delay10,进而 能够保证数据位和应答机位不发生重叠从而问题得到了有效解决
数据现在能够保证了正常的传输

HWT906传感器写入失败问题的处理

原因分析:
时序不对
数据流错误
数据流分析:
时序正确
数据流正确
一天时间过去了 。。。然后尝试了各种办法
实验室另外一个大佬看我处理不好给我提供了个思路,既然正的不行那就试试反向的,好的,做了测试,电脑发给传感器的指令 0x08,说明书里没有,好的,补上这个指令,所有事情work了。…此处省略一万字

4. 总结

首先这次处理HWT906传感器的事件,带给我的不只是一次处理传感器任务的过程,更多的是一次对自己解决问题的思路的审视与思考,首先最高优先级的应该是成熟的设计文档,同时去参考一些可能的问题并且排除法去处理,这样子问题才能尽快得到解决

猜你喜欢

转载自blog.csdn.net/qq_32464727/article/details/119516975
今日推荐