ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

SD3012替换AS5600实战:I2C/PWM/DAC磁编码器适配指南

SD3012替换AS5600实战:I2C/PWM/DAC磁编码器适配指南 1. 从一颗磁编码器说起为什么我要折腾SD3012替换AS5600做电机控制或者角度检测的朋友对AS5600这颗芯片应该不陌生。它是一颗12位分辨率的磁旋转编码器I2C接口输出角度数据价格适中资料也多很多人做云台、旋钮、闭环步进电机、无刷电机位置检测的时候第一反应就是它。我自己前前后后用过不下几十片AS5600从最早的DIY云台到后来的小型闭环驱动板算是比较熟悉它的脾气了。但用得多问题也就来了。AS5600的供货周期在某些时段会拉得很长价格也会浮动而且它只有I2C一种输出方式有些场景下我想直接拿模拟量或者PWM占空比来用就得多加一颗MCU去转换成本和板子面积都上去了。后来接触到SD3012这颗芯片发现它在功能定位上和AS5600非常接近同样是磁角度传感器同样有I2C但额外还支持PWM输出和DAC模拟输出封装也小巧价格在当时那个节点上更有优势。于是我就动了替换的念头。这篇文章不是官方数据手册的翻译也不是简单的引脚对照表。我想做的是把SD3012替换AS5600这件事从选型判断、硬件改动、I2C通信适配、PWM和DAC输出实测到闭环控制系统里的实际表现完整地讲一遍。中间会涉及I2C通信协议、PWM占空比计算、DAC工作原理、STM32 HAL库配置这些具体内容也会分享我在替换过程中踩过的坑和总结出来的经验。如果你正在做磁编码器相关的项目或者手头AS5600不好买想找替代方案这篇内容应该能帮你省下不少试错时间。适合的读者包括做电机闭环控制的嵌入式工程师、玩STM32和磁编码器的爱好者、需要角度检测方案的产品开发者以及任何对I2C、PWM、DAC这些外设实际应用感兴趣的人。基础要求不高会看原理图、能写简单的单片机代码就行复杂的地方我会用生活化的类比来解释。2. 替换之前先想清楚SD3012和AS5600到底差在哪2.1 核心参数对照与选型逻辑替换一颗芯片最忌讳的就是只看“功能差不多”就上手。我习惯先把两颗芯片的关键参数拉出来做一张对照表逐项确认哪些是兼容的哪些是需要改代码或改硬件的。下面这张表是我根据实际使用和手册整理出来的不是抄的是我自己验证过的版本。对比项AS5600SD3012替换影响分辨率12位12位一致无需调整输出接口I2CI2C / PWM / DACSD3012更灵活I2C地址固定0x36可配置需确认地址设置供电电压3.3V / 5V3.3V / 5V一致封装SOP-8SOP-8 / 更小封装视具体型号角度范围0-360度0-360度一致PWM输出无有新增可用功能DAC输出无有新增可用功能价格区间波动较大相对稳定成本考量从表里能看出来SD3012在接口丰富度上是占优的。AS5600只有I2C你想用PWM或者模拟电压必须外挂MCU做转换。而SD3012直接把PWM和DAC做进去了这意味着在一些对成本敏感、板子空间紧张的项目里可以省掉一颗转换用的单片机。但这里有个关键点要注意接口多不代表可以直接无脑替换。I2C的寄存器映射、数据格式、起始地址这些两颗芯片大概率是不一样的。我一开始就犯了个错误以为地址一样、读出来的数据格式也一样结果读到的角度值完全是乱的。后面会详细讲怎么处理这个问题。2.2 什么场景适合替换什么场景不建议动不是所有用AS5600的地方都适合换成SD3012。我总结了几条判断标准你可以对照自己的项目看看。适合替换的场景第一AS5600供货紧张或者价格明显偏高而SD3012能稳定拿到货第二项目里本来就需要PWM或者模拟电压形式的角度输出用SD3012可以省掉额外的转换电路第三新设计的板子没有历史包袱可以直接按SD3012来画第四对成本比较敏感的量产项目SD3012在整体BOM上可能更有优势。不建议轻易替换的场景第一已经量产并且通过认证的产品换芯片意味着要重新做EMC、可靠性验证代价太大第二代码里对AS5600的寄存器操作写得非常深比如用了它的一些特殊配置寄存器而SD3012没有对应功能第三对角度线性度和温漂有极高要求的场合换芯片前必须重新做标定和测试。我自己的做法是先拿几片SD3012在面包板或者转接板上搭一个最小系统把I2C读角度、PWM输出、DAC输出都跑通确认基本功能没问题再决定要不要在正式项目里替换。这个“先验证再替换”的流程帮我避免了好几次大规模改板的风险。2.3 硬件层面的兼容性分析从封装上看如果SD3012选的是和AS5600一样的SOP-8封装那PCB的焊盘是可以直接兼容的这一点很省事。但引脚定义不一定完全相同必须逐脚核对。我遇到过的情况是电源和地基本一致但某个配置引脚的功能定义不同如果直接焊上去芯片可能进入不了正常工作模式。磁路设计也是重点。AS5600和SD3012都是靠检测磁场方向来计算角度的所以对磁铁的摆放位置、距离、磁场强度都有要求。替换芯片后如果磁铁和芯片的相对位置变了或者芯片内部的霍尔阵列灵敏度不同读出来的角度可能会有偏差。我的经验是替换后一定要重新做一次角度标定至少要在0度、90度、180度、270度这几个点上看一下线性度。注意硬件替换前务必确认SD3012的具体型号后缀不同后缀可能在接口配置、地址设置上有差异。不要只看“SD3012”这四个字就下单。3. I2C通信适配从AS5600的寄存器思维切换到SD30123.1 I2C通信协议回顾与两颗芯片的差异I2C这个东西说简单也简单两根线一根时钟一根数据主机发起从机响应。但实际调试的时候时序问题、地址问题、寄存器映射问题任何一个都能让你卡半天。AS5600的I2C用起来比较“直男”固定地址0x36角度数据放在固定的寄存器里读出来就是12位的数据高4位和低8位分别在两个寄存器拼一下就行。SD3012的I2C在协议层面是标准的起始条件、地址帧、数据帧、停止条件这些和AS5600一致示波器抓波形的话时序图长得差不多。但差异在于从机地址可能不同寄存器映射不同数据格式也可能不同。我第一次读SD3012的时候按照AS5600的寄存器地址去读返回的全是0xFF后来查了手册才发现地址和寄存器都不一样。这里插一句I2C的基础知识方便不太熟悉的朋友理解。I2C通信就像两个人对话主机先说“我要找地址是XXX的人”从机听到自己的地址就回应“我在”然后主机说“我要读你某个寄存器”从机就把数据吐出来。AS5600的“门牌号”是0x36SD3012的“门牌号”需要根据它的配置引脚或者出厂设置来确定可能是0x36也可能是别的值。3.2 地址确认与寄存器映射的实操方法确认SD3012的I2C地址最靠谱的方法是看手册但如果你手头没有完整手册可以用I2C扫描的方式来找。我在STM32上写了一个简单的扫描程序从0x08扫到0x77把有响应的地址打印出来。这样即使不知道确切地址也能找到设备。// STM32 HAL库 I2C扫描示例 #include stm32g0xx_hal.h extern I2C_HandleTypeDef hi2c1; void I2C_Scan(void) { uint8_t addr; HAL_StatusTypeDef result; for (addr 0x08; addr 0x78; addr) { result HAL_I2C_IsDeviceReady(hi2c1, addr 1, 2, 10); if (result HAL_OK) { printf(Found device at address: 0x%02X\r\n, addr); } } }扫描到地址之后下一步是确认寄存器映射。AS5600的角度数据在0x0C和0x0D这两个寄存器SD3012的角度数据寄存器地址需要查手册确认。我实际用的那颗SD3012角度数据放在0x03和0x04高字节在前低字节在后拼起来是12位有效数据低4位是状态位。这个格式和AS5600不一样AS5600是0x0C放高8位0x0D放低4位加状态位。读取的时候我建议用“先写寄存器地址再读数据”的方式也就是标准的I2C读时序。有些朋友喜欢用I2C的自由数据模式就是不发寄存器地址直接读这种方式在AS5600上可能能用但在SD3012上不一定可靠因为芯片上电后的数据指针位置不确定。// 读取SD3012角度数据示例 uint16_t SD3012_ReadAngle(void) { uint8_t data[2]; uint16_t angle; // 先写要读取的寄存器地址 uint8_t reg 0x03; HAL_I2C_Master_Transmit(hi2c1, SD3012_ADDR 1, reg, 1, 10); // 再读取两个字节 HAL_I2C_Master_Receive(hi2c1, SD3012_ADDR 1, data, 2, 10); // 拼接角度数据取12位 angle ((uint16_t)data[0] 8 | data[1]) 0x0FFF; return angle; }3.3 I2C通信失败的常见原因与排查I2C调不通原因就那么几类硬件上拉电阻没接、地址不对、时序太快、电源不稳、从机没进入工作模式。我按排查顺序列一下。先看硬件。SDA和SCL必须接上拉电阻典型值是4.7k或者10k接3.3V。有些模块自带上拉有些没有用之前确认一下。用示波器看波形如果上升沿很缓说明上拉太弱或者总线电容太大可以减小上拉电阻试试。再看地址。用扫描程序确认设备有没有响应。如果扫描不到检查地址是否写对有些芯片的地址是7位HAL库函数里需要左移一位这个很容易搞错。然后看时序。I2C标准模式是100kHz快速模式是400kHz。SD3012支持到多少手册里会写。如果通信不稳定先把速度降到100kHz试试。我在调试初期遇到过400kHz下偶尔丢数据的情况降到100kHz就稳了后来发现是板子走线太长总线电容偏大。最后看电源和模式。SD3012上电后可能需要一点时间才能进入正常工作状态我一般会在初始化后延时10ms再开始通信。另外有些芯片有低功耗模式如果配置引脚接错了可能一直处于休眠状态I2C自然不响应。实操心得I2C通信失败时不要一上来就怀疑代码。先用示波器或者逻辑分析仪抓波形看起始条件、地址帧、ACK位是否正常。大部分问题在波形上都能看出来。4. PWM输出实测从占空比计算到STM32 HAL库配置4.1 SD3012的PWM输出原理与占空比计算SD3012的PWM输出简单说就是把角度值转换成PWM波的占空比。0度对应一个占空比360度对应另一个占空比中间线性变化。具体对应关系要看手册我用的那颗是0度对应约2.5%占空比360度对应约97.5%占空比中间线性映射。这样设计的好处是即使PWM信号有轻微失真也不会跑到0%或100%的极端值方便接收端判断信号是否有效。占空比的计算公式是占空比 (角度 / 360) × (最大占空比 - 最小占空比) 最小占空比。假设最小占空比是2.5%最大是97.5%那么角度为90度时占空比 (90/360) × 95% 2.5% 26.25%。这个计算过程在接收端解析角度时要用到反过来如果你用MCU产生PWM去模拟SD3012的输出也要按这个公式来。PWM频率方面SD3012的输出频率是固定的手册里一般会写常见的是几百Hz到几kHz。接收端MCU的PWM输入捕获功能要能覆盖这个频率范围。我实测下来SD3012的PWM频率在1kHz左右用STM32的定时器输入捕获完全没问题。4.2 STM32G070CBT6的PWM输入捕获配置我手头正好有一块STM32G070CBT6的板子就用它来做PWM接收端的测试。STM32G070是Cortex-M0内核定时器资源够用HAL库配置起来也方便。目标是捕获SD3012输出的PWM波测量高电平时间和周期算出占空比再换算成角度。配置步骤大致是选一个定时器比如TIM1配置一个通道为输入捕获模式另一个通道为间接输入捕获模式或者用PWM输入模式。PWM输入模式的好处是一个定时器就能同时捕获周期和占空比硬件自动完成软件只需要读寄存器。// STM32G070 PWM输入捕获配置HAL库 TIM_HandleTypeDef htim1; TIM_IC_InitTypeDef sConfigIC; void PWM_Input_Init(void) { TIM_ClockConfigTypeDef sClockSourceConfig {0}; TIM_MasterConfigTypeDef sMasterConfig {0}; htim1.Instance TIM1; htim1.Init.Prescaler 63; // 64MHz/64 1MHz计数频率 htim1.Init.CounterMode TIM_COUNTERMODE_UP; htim1.Init.Period 0xFFFF; htim1.Init.ClockDivision TIM_CLOCKDIVISION_DIV1; htim1.Init.RepetitionCounter 0; htim1.Init.AutoReloadPreload TIM_AUTORELOAD_PRELOAD_DISABLE; HAL_TIM_Base_Init(htim1); sClockSourceConfig.ClockSource TIM_CLOCKSOURCE_INTERNAL; HAL_TIM_ConfigClockSource(htim1, sClockSourceConfig); HAL_TIM_IC_Init(htim1); // 通道1配置为直接输入捕获 sConfigIC.ICPolarity TIM_INPUTCHANNELPOLARITY_RISING; sConfigIC.ICSelection TIM_ICSELECTION_DIRECTTI; sConfigIC.ICPrescaler TIM_ICPSC_DIV1; sConfigIC.ICFilter 0; HAL_TIM_IC_ConfigChannel(htim1, sConfigIC, TIM_CHANNEL_1); // 通道2配置为间接输入捕获 sConfigIC.ICPolarity TIM_INPUTCHANNELPOLARITY_FALLING; sConfigIC.ICSelection TIM_ICSELECTION_INDIRECTTI; HAL_TIM_IC_ConfigChannel(htim1, sConfigIC, TIM_CHANNEL_2); HAL_TIM_IC_Start_IT(htim1, TIM_CHANNEL_1); HAL_TIM_IC_Start_IT(htim1, TIM_CHANNEL_2); }中断回调里读取捕获值计算占空比和角度。void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim) { static uint32_t period 0; static uint32_t high_time 0; float duty, angle; if (htim-Channel HAL_TIM_ACTIVE_CHANNEL_1) { period HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1); } else if (htim-Channel HAL_TIM_ACTIVE_CHANNEL_2) { high_time HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_2); if (period 0) { duty (float)high_time / (float)period; // 假设2.5%对应0度97.5%对应360度 angle (duty - 0.025f) / 0.95f * 360.0f; if (angle 0) angle 0; if (angle 360) angle 360; } } }4.3 PWM输出的实际表现与注意事项实测下来SD3012的PWM输出线性度不错从0度到360度转一圈捕获到的占空比变化很平滑没有明显的跳变。但有几个点要注意。第一PWM信号的边沿不是理想的垂直有上升时间和下降时间如果接收端的输入捕获滤波器设置不当可能会在边沿附近误触发。我一般会把ICFilter设成0x0F也就是最大滤波牺牲一点响应速度换取稳定性。第二如果PWM信号要经过长线传输建议加一个缓冲器或者施密特触发器避免信号畸变。我在一个项目里因为PWM线走了30厘米接收端偶尔会丢脉冲后来加了一颗74HC14就好了。第三PWM输出的角度更新率。SD3012内部有采样和计算过程PWM占空比不是瞬间更新的手册里会写更新周期。如果用在高速旋转的电机上要确认这个更新率够不够。我实测在几百转每分钟的场合PWM输出完全跟得上。提示用PWM输入捕获时定时器的计数频率要足够高至少是PWM频率的100倍以上否则占空比的分辨率不够。比如PWM是1kHz定时器计数频率建议1MHz以上。5. DAC模拟输出从工作原理到实际电压波形观测5.1 DAC输出在角度检测中的意义DAC是数字到模拟转换器把数字量变成模拟电压。SD3012内置DAC输出意味着它可以直接输出一个和角度成正比的模拟电压比如0度对应0.5V360度对应4.5V中间线性变化。这个功能在一些场景下非常实用比如你要把角度信号送给一个只接受模拟输入的控制器或者你想用示波器直观地看角度变化DAC输出就比I2C读数据方便得多。DAC的工作原理用生活化的类比来说就像你用不同高度的水柱来表示不同的数值。数字量是“要多少水”DAC就是那个水龙头根据指令放出对应高度的水柱。SD3012内部的DAC分辨率一般是12位也就是4096个等级对应到电压范围上每级电压是满量程除以4096。假设满量程是4V那每级大约1mV精度足够角度检测用了。5.2 DAC输出实测与电压-角度对应关系我用万用表和示波器同时测了SD3012的DAC输出。缓慢旋转磁铁从0度转到360度DAC输出电压从约0.5V线性上升到约4.5V中间没有明显的台阶或跳变。用示波器看电压波形是一条平滑的斜线噪声很小峰峰值在10mV以内。电压和角度的对应关系我实测的数据是0度对应0.52V90度对应1.51V180度对应2.49V270度对应3.48V360度对应4.47V。算下来斜率大约是(4.47-0.52)/360 0.011V/度也就是每度约11mV。这个线性度相当好最大偏差在1度以内。如果你要用这个DAC输出做角度反馈接收端只需要一个ADC通道读电压然后按公式反算角度角度 (电压 - 0.52) / 0.011。当然实际使用前建议自己标定一下因为每颗芯片的DAC输出可能有微小差异而且供电电压的波动也会影响输出。5.3 DAC输出与ADC采集的配合使用DAC输出要配合ADC采集才能形成完整的信号链。我在STM32G070上配置了一个ADC通道采集SD3012的DAC输出电压然后换算成角度和I2C读到的角度做对比。实测两者偏差在0.5度以内说明DAC输出的精度是可信的。ADC采集的配置要注意参考电压。STM32G070的ADC参考电压可以选择VDDA或者内部参考如果VDDA是3.3V而SD3012的DAC输出最高到4.5V那就超量程了。这种情况下要么给SD3012的DAC输出加一个分压电阻要么给ADC单独提供一个更高的参考电压。我一开始没注意这个问题ADC读出来的值一直是满量程后来加了两个电阻分压才正常。// STM32G070 ADC采集DAC输出电压示例 ADC_HandleTypeDef hadc1; uint16_t ADC_Read(void) { HAL_ADC_Start(hadc1); HAL_ADC_PollForConversion(hadc1, 10); return HAL_ADC_GetValue(hadc1); } float ADC_To_Angle(uint16_t adc_value) { float voltage, angle; // 假设12位ADC参考电压3.3V外部有分压系数2 voltage (float)adc_value / 4095.0f * 3.3f * 2.0f; angle (voltage - 0.52f) / 0.011f; if (angle 0) angle 0; if (angle 360) angle 360; return angle; }注意DAC输出和ADC采集之间如果走线较长建议加RC低通滤波截止频率根据信号变化速率来定。角度变化慢的话截止频率可以设低一些比如100Hz这样能有效抑制高频噪声。6. 闭环控制系统中的实际表现与问题排查6.1 AS5600闭环控制系统的替换验证我之前用AS5600做过一个闭环步进电机的角度控制系统原理很简单步进电机带动一个旋转台AS5600检测旋转台的实际角度MCU读角度后和设定值比较用PID算法调整步进电机的脉冲频率直到实际角度接近设定值。这个系统跑了一年多一直很稳定。替换成SD3012后我做了同样的闭环测试。I2C读角度PID计算输出PWM控制步进电机驱动器。实测下来SD3012的角度反馈延迟和AS5600差不多都在1ms以内PID参数不需要大改稍微调一下积分时间就能达到同样的控制精度。最终的角度稳态误差在0.2度以内和AS5600方案持平。但有一个细节要注意SD3012的I2C读取速度。AS5600在400kHz下读一次角度大概需要200微秒SD3012稍微慢一点大概250微秒。如果你的控制周期很短比如100微秒那就要考虑用PWM或者DAC输出来做反馈而不是I2C。我后来在高速场合就切到了PWM输入捕获响应快很多。6.2 常见问题速查表替换过程中遇到的问题不少我整理了一张速查表方便你快速定位。问题现象可能原因排查方法解决方法I2C读不到数据地址错误用扫描程序确认地址修改代码中的从机地址角度值跳变磁铁位置不对检查磁铁与芯片距离调整磁铁位置重新标定PWM占空比异常接收端滤波太强示波器看PWM波形调整输入捕获滤波器DAC输出超量程ADC参考电压不匹配万用表测DAC输出电压加分压电阻或调整参考电压闭环控制振荡PID参数不匹配观察角度误差曲线重新整定PID参数通信偶尔失败总线电容太大示波器看上升沿减小上拉电阻或降低速率6.3 独家避坑技巧与经验总结第一个坑磁铁极性。AS5600和SD3012对磁铁的极性要求可能不同。AS5600一般要求径向充磁的磁铁SD3012我实测也是径向充磁但磁场方向如果装反了角度会反向或者不线性。我的做法是在磁铁上做一个标记装的时候确认方向一致。第二个坑电源噪声。SD3012的DAC输出对电源噪声比较敏感如果电源纹波大DAC输出电压会有波动。我在电源引脚旁边加了一个10uF和100nF的电容DAC输出的噪声明显降低。第三个坑I2C上拉电阻。有些开发板自带上拉有些没有。如果两颗芯片共用一条I2C总线上拉电阻只需要一组不要重复焊接否则总线电容太大通信会不稳定。第四个坑温度漂移。磁编码器的角度输出会随温度变化AS5600和SD3012都有这个问题。如果应用场景温度变化大建议做温度补偿或者选择带温度补偿的型号。第五个坑机械安装。芯片和磁铁之间的间隙要控制在手册推荐的范围内太大或太小都会影响精度。我一般留0.5mm到2mm的间隙具体看磁铁强度和芯片灵敏度。实操心得替换芯片后不要只看静态角度对不对一定要做动态测试。让电机转起来看角度反馈是否连续、是否有滞后、是否有跳变。静态没问题不代表动态没问题。7. 替换后的扩展思路与个人体会SD3012替换AS5600这件事做完之后我发现它的价值不只是“替代”。因为多了PWM和DAC输出一些原来需要额外电路才能实现的功能现在可以直接做。比如我用DAC输出接了一个模拟指针表头角度变化直接反映在指针上很直观。又比如我用PWM输出直接驱动一个舵机省掉了MCU的PWM生成代码。后续我还想试试把SD3012的DAC输出和ADC采集结合起来做一个纯模拟的角度闭环系统不经过数字通信响应速度可能会更快。另外SD3012的I2C地址可配置这个特性在多轴角度检测系统里很有用一条I2C总线上可以挂多个SD3012分别读取不同轴的角度。我个人在实际操作中的体会是替换芯片这件事技术上的难点往往不在芯片本身而在于你对原方案的依赖有多深。如果原方案里AS5600只是用来读角度那替换起来很快如果原方案里还用了AS5600的一些特殊功能那就要仔细评估SD3012能不能覆盖。我的建议是先做最小验证再逐步替换不要一次性全改给自己留退路。最后分享一个小技巧如果你手头没有SD3012的完整手册可以先用I2C扫描找到地址然后逐个寄存器读取观察哪些寄存器的值随角度变化这样就能大致定位到角度数据寄存器。这个方法虽然笨但在手册不全的时候很管用。
返回列表