发现问题

客户反馈说我们的硬件关机漏电流很大,但是拔掉电池之后再上电(仍处于关机状态)就会恢复为 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. JS逆向实战3——AESCBC 模式解密

    爬取某省公共资源交易中心 通过抓包数据可知 这个data是我们所需要的数据,但是已经通过加密隐藏起来了 分析 首先这是个json文件,我们可以用请求参数一个一个搜 但是由于我们已经知道了这是个json ...

  2. 版本控制工具Git介绍-01

    使用版本控制工具是为了方便团队开发,比如多人共同维护一个项目的时候,用版本控制工具可以很方便的维护项目代码,如果哪天你改了一个版本,出问题了,我们也可以很快的找到你改了什么,这里介绍使用比较多的版本控 ...

  3. JAVA 用分苹果来理解本题

    思路 其实这是一道非常经典的分苹果问题:有m个一样的苹果和n个一样的盘子,把苹果放盘子里,每个盘子允许0-m个苹果,求问有多少种分法? 与本题的共通之点在于,输入的正整数可以看成m个苹果,拆分出的加数 ...

  4. laravel框架 forelse和foreach

    1. @forelse($data as $v) 循环数据内容..... @empty 数据为空提示... @endforelse 2. @foreach($data as $v) 循环数据内容... ...

  5. python安装dlib库报错

    问题描述 我是debain 系的linux系统没遇到这个问题,在centos系统遇到的 Collecting dlib Downloading http://mirrors.cloud.aliyunc ...

  6. @responseBody 返回更多数据

    @responseBody:注解的作用是将controller的方法返回的对象通过适当的转换器转换为指定的格式之后,写入到response对象的body区,通常用来返回JSON数据或者是XML数据,需 ...

  7. JSON提取器中串联一个接口的多个值传给下个接口(compute concatenation var的实际使用场景)

    实际场景:某功能在前端支持选择多条数据后点击提交,表现在接口是,一次传了多个Id. 问题:需要将上个接口的多个Id串联,传给提交接口. 处理方式:通过JSON提取器勾选:compute concate ...

  8. 【JVM调优】Day03:GC参数、OOM出现方式、调优实战

    一.常用GC参数(20个左右即可) 1.各种垃圾回收器的参数 PS + PO 常用的只有几十个 CMS的比较多,不建议使用 G1的常用参数简单 ZGC只有三个参数 二.OOM出现的方式 1.写一个让内 ...

  9. 【JVM调优】Day01:Garbage的概念、垃圾回收的算法(标记清除、拷贝、标记压缩)、各种垃圾回收器(Serial、Parallel、CMS并发)及存在的问题

    〇.前言 简历写上:熟悉GC常用算法,熟悉常见垃圾回收器.具有实际JVM调优实战经验 瞬间涨3k 一.什么是garbage Java中垃圾回收器自动进行垃圾回收,不用自己回收 new 对象在内存中,c ...

  10. SQL注入问题/触发器trigger/事务/事物隔离

    SQL注入问题 本质:利用特殊符号的组合产生特殊的含义,从而避开正常的业务逻辑 select * from userinfo where name='jason' -- kasdjksajd' and ...