此问题在此处已有答案:
Arduino Uno is making errors when doing calculations(2个答案)
Arduino computing error - giving negative values when it shouldn't(2个答案)
5天前关闭。
我试图计算电位计的Angular 值,所以我需要乘以180,然后除以量程。这样做后,我注意到得到的数字不是我期望的数字,所以我开始调试,只乘以180,并意识到输出不是预期的那样。**以下是输出奇怪读数的简单代码:*`
#define POTENTIOMETER_PIN A0
int val;
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
}
// put your main code here, to run repeatedly:
void loop()
{
val = analogRead(POTENTIOMETER_PIN);
Serial.println(val*180);
delay(250);
}
`
预期值在(0到1023)*180之间,而不是串行监视器输出值,例如:18932年-18752年-18572年-18392年-18392年
2条答案
按热度按时间lbsnaicq1#
看一看您的用例中的
map()
函数https://www.arduino.cc/reference/en/language/functions/math/map/
在内部,这使用了比不起眼的
int
更大的类型,使用了long
,它(可能)是32位而不是16位从上述文档中
这种方法更适合您,并且可以正确地进行数学运算的原因是,16位数字不包含足够的乘法精度,而
map()
在进行数学运算时,内部使用32位数字来表示值!具体来说,如果在您依赖16位数学运算的逻辑过程中,值超出了~32768的范围,它将 * 回绕 * 并变为负值!
这被称为Integer Overflow,维基百科文章链接了一个使用汽车里程表的很好的演示
第100,000英里 * 溢出 * 并绕回为1,因为第一个数字没有空间,因此被截断
一些人更详细地阐述了Arduino上的
int
文档中的观点,特别是因为尽管存在很多争论(包括 * 为什么 * Arduino选择提供int
),但通常好的做法是始终准确地指定您所追求的类型,如uint32_t
,而不是依赖int
,后者在不同的设备目标上可能有不同的大小,这令人沮丧https://www.arduino.cc/reference/en/language/variables/data-types/int/
在Arduino Uno(和其他基于ATmega的板卡)上,int存储一个16位(2字节)的值,其范围为-32,768到32,767(最小值为-2^15,最大值为(2^15)- 1)。
在基于Arduino Due和SAMD的开发板上(如MKR 1000和Zero),int存储一个32位(4字节)的值,其范围为-2,147,483,648到2,147,483,647(最小值为-2^31,最大值为(2^31)- 1)。
b4lqfgs42#
您的编译器似乎将int定义为16位有符号数。
因此,存在32767到-32768的限制。
您超出了此值,因此值“环绕”。
请尝试将代码更改为使用“long”而不是“int”。