如何用C++计算卧式圆柱储罐液体体积?ESP32计算偏差求助
卧式圆柱储罐液体体积计算问题排查与修正
原代码的核心问题
- 公式完全错误:你写的式子既不是正确的弓形面积,也没乘以储罐长度
length——卧式圆柱的体积是液体横截面积(弓形面积)× 储罐长度,原代码连最基础的体积计算逻辑都缺失。 - 圆周率精度不足:用
3.14代替π会引入不必要的计算误差,应该用标准数学库的M_PI常量。 - 缺少输入校验:没考虑
height的合法范围(必须在0到2*radius之间,也就是0到储罐直径),传感器异常值会导致计算崩溃或结果异常。
正确的计算逻辑
卧式圆柱的液体横截面积是弓形面积,分两种情况计算:
- 当液体高度
height ≤ radius(半罐以下):
弓形面积 = 扇形面积 - 三角形面积
公式:radius² × acos((radius - height)/radius) - (radius - height) × sqrt(2×radius×height - height²) - 当液体高度
height > radius(半罐以上):
弓形面积 = 圆面积 - 空出部分的弓形面积
公式:M_PI×radius² - [radius² × acos((height - radius)/radius) - (height - radius) × sqrt(2×radius×height - height²)]
最终体积 = 弓形面积 × 储罐长度length
修正后的代码
#include <math.h> // 必须包含math.h才能使用M_PI、acos、sqrt double radius = 100; double height = 50; // 传感器读取的水深,单位cm double length = 450; // 储罐长度,单位cm double volume; // 最终体积,单位cm³(1L=1000cm³) void calculateVolume() { // 输入合法性校验 if (height < 0) { volume = 0; return; } if (height >= 2 * radius) { volume = M_PI * radius * radius * length; return; } double segmentArea; if (height <= radius) { segmentArea = (radius * radius) * acos((radius - height)/radius) - (radius - height) * sqrt(2 * radius * height - height * height); } else { double emptyHeight = 2 * radius - height; segmentArea = M_PI * radius * radius - [(radius * radius) * acos((radius - emptyHeight)/radius) - (radius - emptyHeight) * sqrt(2 * radius * emptyHeight - emptyHeight * emptyHeight)]; } volume = segmentArea * length; }
注意事项
- ESP32编译时要确保开启数学库支持(默认开启),如果遇到
M_PI未定义的问题,可在#include <math.h>前添加#define _USE_MATH_DEFINES。 - 传感器读取的
height建议做滤波处理,避免数据波动导致计算值跳变。 - 最终体积单位是立方厘米,转换成升只需除以1000。
内容的提问来源于stack exchange,提问作者Hansie
相关产品推荐
相关产品推荐

