您尚未登录。

楼主 # 2024-07-12 08:47:28

Gentlepig
会员
注册时间: 2018-10-24
已发帖子: 1,379
积分: 1344.5

betaflight源码中,adc转电压值这个函数没看懂。

src/main/sensors/voltage.c中的函数:

159 STATIC_UNIT_TESTED uint16_t voltageAdcToVoltage(const uint16_t src, const voltageSensorADCConfig_t *config)
  1 {
  2     // calculate battery voltage based on ADC reading                                                
  3     // result is Vbatt in 0.01V steps. 3.3V = ADC Vref, 0xFFF = 12bit adc, 110 = 10:1 voltage divider (10k:1k) * 100 for 0.01V
  4     return ((((uint32_t)src * config->vbatscale * getVrefMv() / 10 + (0xFFF * 5)) / (0xFFF * config->vbatresdivval)) / config->vbatresdivmultiplier);
  5 }   

getVreMv()函数,默认返回是3300,对应3300mV;
config->vbatscale,默认值是110;
config->vbatresdivval,默认值是10;
config->vbatresdivmultiplier,默认值是1.

找到个at32f435的原理图,可能不一定完全对应的上,原理图里只用了一个adc,用的10K:1K测量的电池电压。
按我的逻辑,(adc值/0xfff)*3300,得到测量的adc电压值,然后放大11倍,就是电池电压了。可看这个公式,对应不上。

-----------------------------------------------------------

如果把原式中的+(0xfff*5)去掉,精简下:
((((uint32_t)src * config->vbatscale * getVrefMv() / 10) / (0xFFF * config->vbatresdivval)) / config->vbatresdivmultiplier);
= src * 110 * 3300 / 10 / (0xFFF * 10) / 1
= src * 110 * 3300 / 0xFFF
这样看,就和我的逻辑计算公式差不多了,只是查了10倍, 那么原式中的+0xFFF*5,有什么作用呢?

-----------------------------------------------------------

单独把0xFFF*5部分拿出来再除以后续部分:
0xFFF*5 / (0xFFF * 10) / 1 = 0.5

这么看,这部分是为了四舍五入?

感觉这个转换函数写的好繁琐。

----------------------------------------------

算错,src * 110 * 3300 / 10 / (0xFFF * 10) / 1, 应该是:
= src * 110 * 3300 / 0xFFF * 10 * 10
= src * 11 * 3300 / 0xFFF * 10
可以看作将adc值转换为电压值后,按分压电阻放大11备得到mV单位的电池电压,再除以10得到0.01V单位的电池电压。

算是明白了,就是觉得这个公式好繁琐。

最近编辑记录 Gentlepig (2024-07-12 10:42:50)

离线

楼主 #1 2024-07-12 10:20:20

Gentlepig
会员
注册时间: 2018-10-24
已发帖子: 1,379
积分: 1344.5

Re: betaflight源码中,adc转电压值这个函数没看懂。

经飞控群里二木仙人指点,去看了inav的代码:

455 uint16_t getVBatSample(void) {
  1     // calculate battery voltage based on ADC reading
  2     // result is Vbatt in 0.01V steps. 3.3V = ADC Vref, 0xFFF = 12bit adc, 1100 = 11:1 voltage divider (10k:1k)
  3     return (uint64_t)adcGetChannel(ADC_BATTERY) * batteryMetersConfig()->voltage.scale * ADCVREF / (0xFFF * 1000);
  4 }

这个就很容易理解了。

最近编辑记录 Gentlepig (2024-07-12 10:20:34)

离线

页脚

工信部备案:粤ICP备20025096号 Powered by FluxBB

感谢为中文互联网持续输出优质内容的各位老铁们。 QQ: 516333132, 微信(wechat): whycan_cn (哇酷网/挖坑网/填坑网) service@whycan.cn