发现问题

客户反馈说我们的硬件关机漏电流很大,但是拔掉电池之后再上电(仍处于关机状态)就会恢复为 16~20uA 左右。这让我也讶异,因为亲自测试过,漏电流只有 MCU 的休眠电流 16~20uA 左右 (包含一些电子元器件),远远低于项目要求的 <100uA。

观看客户的复现步骤,发现客户每次在关机之前,都会通过触摸触发设备一些功能,而我的测试是开机之后,等上位机运行正常就直接关机(未驱动电机转动)。

分析问题

触摸触发的功能其中最直观的是让电机转动,因此高度怀疑跟电机驱动部分功能有关,通过断开上位机,直接通过串口控制设备转一下电机,然后再关机,果然复现问题,漏电流为 380uA 左右。当问题出现之后,必须拔掉电池再重新上电,电流才会下降到正常的范围(20uA 左右)。

电机驱动 IC 有 6 颗,分别平均分布在 A、B 两块副板上,拔掉副板的电机驱动连接线,电流直接降至 200uA 左右,反复测试都是如此,跟带不带电机没有太大关系。因此确认与电机驱动IC有关,通过示波器测量控制芯片的控制信号,确认软件控制逻辑正确,此时发现该电机芯片的电源不受控,直接通过电池供电。

电机驱动IC型号是 DW7888,我们查到规格书,待机电流 <2uA,因此即使电源未关断,在待机模式下,漏电流也不至于那么大才对。

然后回想问题的复现流程,开机之后默认为待机模式,为什么一驱动电机,再进入待机模式,就会出现问题呢?

这与芯片规格书描述不符呀?跟我们的硬件工程师沟通之后,让我在出现问题的时候让芯片进入刹车模式,然后再进入待机模式。想到规格书有写到刹车模式是可以释放马达能量的,觉得有机会,顺手就用飞线出来的3.3V,同时给其中一颗电机驱动IC的两个输入信号碰一下(FI\BI 都置高电平),奇迹出现了,电流居然下降了 60uA 左右,依次将所有的电机都这么操作一次,电流最终降到 20uA 的水平,说明每颗驱动IC漏电流在 60uA 左右。

我很兴奋的马上通过 MCU 来模拟这种操作,结果让人大跌眼镜,居然没效果,拿出示波器来测量,发现确实有给出刹车信号,百思不得其解(原因下文有解)。

最后电话咨询供应商,供应商拖了蛮久才回复说是这个芯片本身的待机电流就是在  50uA~60uA 左右,但是这个回复解释不了我们实测的现象,就请他帮忙联系芯片原厂的工程师沟通一下这事情。

解决问题

跟原厂技术重新沟通了整个情况,最后他们确认这是该芯片的设计缺陷,鉴于我们的新发现,他也十分诧异,希望我们寄一套平台给他们,分析原因。

最后给出的答复是 FI、BI 两个信号同时拉低的间隔要非常短,而我们两个信号拉低间隔了 900ns,他们用 8M 的 MCU 同时设置拉低(受示波器精度影响,测量不出时差),就能解决此问题。

恍然大悟,我们咋没想到呢,我们当时测试的时候是将 DW7888 输入信号飞的线拧在一块,然后再去碰 3.3V 只高电平,从而进入刹车模式,电压是同时传给两个信号。而 MCU 是顺序执行代码,所以会有先后之分,总会有间隔。只是我们 MCU 的主频是 72M 没理由比他们原厂 8M 的 MCU 还慢,直接上代码分析,看有没有优化空间。

我们当时模拟的代码,考虑可移植和可配置,通过一个数组来存储每个在配置文件配置的 GPIO,因此实现如下:

测的波形如下,两个控制信号间隔约有 900ns:

上图的代码是逐个引脚控制,两根引脚控制信号的时间间隔有 900ns,可以移除循环语句和同时设置多个寄存器位,来缩短控制信号的时间间隔。因此修改代码如下:

测的波形如下,同组的 GPIO 几乎是同时拉低(示波器精度有限):

发现有一颗还存在 60uA 电流,查看原理图发现该芯片的 FI\BI 控制脚分别在GPIOA和GPIOB组,测得波形如下(500ns):

由于 GPIOA、GPIOB 两组是分别通过调用函数来实现拉低,考虑到函数入栈出栈的消耗,采用直接操作寄存器的方式:

测得波形如下,间隔约 124ns (这里直观地展现出调用普通函数的入栈出栈消耗有多大了,72MHz的主频,慢了4倍多):

测得结果通过,16uA:

最终补丁

上面的只是工程验证,实际应用还需要考虑到代码维护性以及稳定性,如需要有明确的注释,以及需要考虑中断的影响。

--- configuration.h	2020-12-10 11:28:07.000000000 +0800
+++ configuration.h 2020-12-10 11:23:40.000000000 +0800
@@ -169,12 +169,35 @@
#define MOTOR_FI_RFRONT_PWM_CHANNEL 8
#define MOTOR_BI_LBACK_PWM_CHANNEL 9 // 左后电机
#define MOTOR_FI_LBACK_PWM_CHANNEL 10
#define MOTOR_BI_RBACK_PWM_CHANNEL 11 // 右后电机
#define MOTOR_FI_RBACK_PWM_CHANNEL 12 +// ------------------------------------ 注意(lmx:20201210) -----------------------------------
+
+// 修复 DW7888 芯片缺陷(需要注意此相关代码仅适用于 DW7888 驱动芯片):
+// 1.当驱动电机之后再进入待机模式, 每颗芯片会存在 60uA 左右的漏电流, 而这些芯片的电源不受控制
+// 2.有效修复方法是先进入刹车模式, 再进入待机模式, 两个输入信号同时拉低的时间一定要小于 500ns
+// 3.由于当前硬件设计有一颗驱动芯片分别用了 GPIOA-15\GPIOB-3 两组引脚, 因此不能一次性同时设置
+// 4.实测可以通过直接操作寄存器的方式缩短两组 GPIO 控制时间间隔(124ns):
+// unsigned int groupa_allpin = FIX_DW7888_CHIP_BUG_GPIO_PIN_1;
+// unsigned int groupb_allpin = FIX_DW7888_CHIP_BUG_GPIO_PIN_2;
+// GPIO_BOP(FIX_DW7888_CHIP_BUG_GPIO_GROUP_1) = groupa_allpin;
+// GPIO_BOP(FIX_DW7888_CHIP_BUG_GPIO_GROUP_2) = groupb_allpin;
+// delay_1ms(100U);
+// disable all interrupt code
+// GPIO_BC(FIX_DW7888_CHIP_BUG_GPIO_GROUP_1) = groupa_allpin;
+// GPIO_BC(FIX_DW7888_CHIP_BUG_GPIO_GROUP_2) = groupb_allpin;
+// enable all interrupt code
+
+#define FIX_DW7888_CHIP_BUG_GPIO_GROUP_1 GPIOA
+#define FIX_DW7888_CHIP_BUG_GPIO_PIN_1 (GPIO_PIN_9 | GPIO_PIN_8 | GPIO_PIN_15 | GPIO_PIN_10 | GPIO_PIN_11)
+#define FIX_DW7888_CHIP_BUG_GPIO_GROUP_2 GPIOB
+#define FIX_DW7888_CHIP_BUG_GPIO_PIN_2 (GPIO_PIN_13 | GPIO_PIN_12 | GPIO_PIN_15 | GPIO_PIN_14 | GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_3)
+// ------------------------------------ 注意(lmx:20201210) -----------------------------------
+
// Action 计时模块
#define CFG_ACTION_TIMER TIMER13
#define CFG_ACTION_TIMER_RCU_CLOCK RCU_TIMER13
#define CFG_ACTION_TIMER_IRQ_NUMBER TIMER13_IRQn
#define CFG_ACTION_TIMER_IRQ_FUNCTION TIMER13_IRQHandler
--- Interface\common.c	2020-12-10 11:28:40.000000000 +0800
+++ Interface\common.c 2020-12-10 11:26:15.000000000 +0800
@@ -18,12 +18,43 @@
#include "common.h"
#include "sensor_infra_red.h"
#include "motor_control.h"
#include "action_process.h"
#include "function_switch.h" +// ------------------------------------ 注意(lmx:20201210) -----------------------------------
+// 修复 DW7888 芯片缺陷(需要注意此相关代码仅适用于 DW7888 驱动芯片):
+// 1.当驱动电机之后再进入待机模式, 每颗芯片会存在 60uA 左右的漏电流, 而这些芯片的电源不受控制
+// 2.有效修复方法是先进入刹车模式, 再进入待机模式, 两个输入信号同时拉低的时间一定要小于 500ns
+// 3.由于当前硬件设计有一颗驱动芯片分别用了 GPIOA-15\GPIOB-3 两组引脚, 因此不能一次性同时设置
+// 4.实测可以通过直接操作寄存器的方式缩短两组 GPIO 控制时间间隔(124ns):
+// ------------------------------------ 注意(lmx:20201210) -----------------------------------
+static void dw7888_low_power_mode()
+{
+ unsigned int groupa_allpin = FIX_DW7888_CHIP_BUG_GPIO_PIN_1;
+ unsigned int groupb_allpin = FIX_DW7888_CHIP_BUG_GPIO_PIN_2;
+
+ // 刹车模式
+ GPIO_BOP(FIX_DW7888_CHIP_BUG_GPIO_GROUP_1) = groupa_allpin;
+ GPIO_BOP(FIX_DW7888_CHIP_BUG_GPIO_GROUP_2) = groupb_allpin;
+ delay_1ms(100U);
+
+ // 待机模式
+ __disable_irq();
+ GPIO_BC(FIX_DW7888_CHIP_BUG_GPIO_GROUP_1) = groupa_allpin;
+ GPIO_BC(FIX_DW7888_CHIP_BUG_GPIO_GROUP_2) = groupb_allpin;
+ __enable_irq();
+
+ return ;
+}
+
+static void common_fix_chip_bug_release()
+{
+ dw7888_low_power_mode();
+}
+
static void common_periph_clock_init()
{
// 系统滴答时钟初始化
systick_config(); // 启用各个公共时钟
@@ -85,14 +116,14 @@
simple_sensor_release();
adc_control_release();
led_control_release();
master_transfer_release();
power_manager_release();
time_base_release();
+ common_fix_chip_bug_release();
common_periph_clock_release();
-
return ;
} // 进入升级模式(实质是跳转到 boot )
void common_enter_update_mode(void)
{

问题总结

1. 以后写完程序之后要测试低功耗的时候,应该全功能跑完之后,再关机来看漏电流。

2. 后面我们发现芯片承认书里面的 DW7888 规格书里面的被改为待机电流为 <50uA,也就是一开始选型就能发现问题,只是我们硬件工程师不够细心(虽然有他签字),这也从侧面证实了供应商其实是知道有这么一个问题,原厂之前应该也不知道有这种解决办法。

3. 像多个信号需要同时触发,使用手动去测试可以通过,但是MCU模拟却不通过,就需要首先考虑到 GPIO 之间的间隔时间,因为 MCU 代码是串行执行的,不像 FPGA 可以通过一个时钟触发多个代码块同时执行。那么简单的道理,居然让我给忽略了,忽略了,忽略了,唉。。。

【分析笔记】DW7888 马达驱动芯片待机模式漏电流过高的问题的更多相关文章

  1. 并发编程学习笔记(9)----AQS的共享模式源码分析及CountDownLatch使用及原理

    1. AQS共享模式 前面已经说过了AQS的原理及独享模式的源码分析,今天就来学习共享模式下的AQS的几个接口的源码. 首先还是从顶级接口acquireShared()方法入手: public fin ...

  2. STM32学习笔记(九) 外部中断,待机模式和事件唤醒

    学会知识只需要不段的积累和提高,但是如何将知识系统的讲解出来就需要深入的认知和系统的了解.外部中断和事件学习难度并不高,不过涉及到STM32的电源控制部分,还是值得认真了解的,在本文中我将以实际代码为 ...

  3. 4.View绘制分析笔记之onDraw

    上一篇文章我们了解了View的onLayout,那么今天我们来学习Android View绘制三部曲的最后一步,onDraw,绘制. ViewRootImpl#performDraw private ...

  4. 2.View绘制分析笔记之onMeasure

    今天主要学习记录一下Android View绘制三部曲的第一步,onMeasure,测量. 起源 在Activity中,所有的View都是DecorView的子View,然后DecorView又是被V ...

  5. 【转载】Instagram架构分析笔记

    原文地址:http://chengxu.org/p/401.html Instagram 架构分析笔记 全部 技术博客 Instagram团队上个月才迎来第 7 名员工,是的,7个人的团队.作为 iP ...

  6. 《linux 内核全然剖析》 fork.c 代码分析笔记

    fork.c 代码分析笔记 verifiy_area long last_pid=0; //全局变量,用来记录眼下最大的pid数值 void verify_area(void * addr,int s ...

  7. ReentrantReadWriteLock源码分析笔记

    ReentrantReadWriteLock包含两把锁,一是读锁ReadLock, 此乃共享锁, 一是写锁WriteLock, 此乃排它锁. 这两把锁都是基于AQS来实现的. 下面通过源码来看看Ree ...

  8. 3.View绘制分析笔记之onLayout

    上一篇文章我们了解了View的onMeasure,那么今天我们继续来学习Android View绘制三部曲的第二步,onLayout,布局. ViewRootImpl#performLayout pr ...

  9. 1.Android 视图及View绘制分析笔记之setContentView

    自从1983年第一台图形用户界面的个人电脑问世以来,几乎所有的PC操作系统都支持可视化操作,Android也不例外.对于所有Android Developer来说,我们接触最多的控件就是View.通常 ...

  10. Hadoop阅读笔记(七)——代理模式

    关于Hadoop已经小记了六篇,<Hadoop实战>也已经翻完7章.仔细想想,这么好的一个框架,不能只是流于应用层面,跑跑数据排序.单表链接等,想得其精髓,还需深入内部. 按照<Ha ...

随机推荐

  1. 关于入门深度学习mnist数据集前向计算的记录

    import osimport lr as lrimport tensorflow as tffrom pyspark.sql.functions import stddevfrom tensorfl ...

  2. java学习之JSON

    0X00前言 JSON可以说是javascript的一种数据类型,我们学习JSON是为了在客户端的数据给读取出来,官方的解释是:概述:JSON(JavaScript Object Notation, ...

  3. K8s集群环境搭建

    K8s集群环境搭建 1.环境规划 1.1 集群类型 Kubernetes集群大体上分为两类:一主多从和多主多从 一主多从:一台master节点和多台node节点,搭建简单,但是有单机故障风险,适用于测 ...

  4. Crony 一个基于Go语言实现的分布式定时任务管理平台

    crony - 分布式定时任务管理平台 1. 基本介绍 1.1 项目背景 项目中存在许多定时任务,很多代码写法都是采取见缝插针式的写法或者直接丢到task服务里面写,存在以下问题 服务多实例时执行定时 ...

  5. go slice不同初始化方式性能&数组比较

    go语言开发中,slice是我们常用的数据类型之一,也是因为它的灵活性,自己也很少使用数组,当然我也知道它的一些特性,不过没有真实的去验证它,因为大多数使用场景没必要对code太过苛刻,但是如果封装作 ...

  6. JavaScript入门⑥-WEB浏览器API

    JavaScript入门系列目录 JavaScript入门①-基础知识筑基 JavaScript入门②-函数(1)基础{浅出} JavaScript入门③-函数(2)原理{深入}执行上下文 JavaS ...

  7. 手摸手,使用Dart语言开发后端应用,来吧!

    前言 这几天连续发了几篇关于 Dart 开发后端应用的文章,主要是介绍了 Dart 的一些优点,比如异步任务,并发处理,编译部署等等. 俗话说,光说不练假把式,今天我们来真正开始一个 Dart 后端应 ...

  8. vivo 云原生容器探索和落地实践

    作者:vivo 互联网容器团队- Pan Liangbiao 本文根据潘良彪老师在"2022 vivo开发者大会"现场演讲内容整理而成.公众号回复[2022 VDC]获取互联网技术 ...

  9. HTTP协议图文简述--HTTP/HTTPS/HTTP2

    01.准备 1.1.先了解下网络模型/TCP HTTP 连接是建立在 TCP* 协议之上的,其数据传输功能是由TCP完成的,那TCP又是什么呢? TCP 是一个单纯用来建立通信连接,并传输数据的基础协 ...

  10. k8s本地联调工具kt-connect

    1.Kt Connect简介 KT Connect ( Kubernetes Developer Tool ) 是轻量级的面向 Kubernetes 用户的开发测试环境治理辅助工具.其核心是通过建立本 ...