Неожиданные отрицательные значения из функции abs(), встроенной в AnalogRead

При выборке из A0 с сигналом 0–5 В на Arduino Micro с помощью приведенного ниже кода я получаю некоторые отрицательные значения.

int sensor = 0;
sensor = abs(analogRead(A0) - 512);

Значения:

77
25
-74
-58
46
113
-74
102
-91
-51
-126
47
31

При запуске (очевидно) математически эквивалентного кода ниже я получаю исключительно положительные значения.

int sensor = 0;
sensor = analogRead(A0);
sensor = sensor - 512;
sensor = abs(sensor);

Я не думаю, что это целочисленное переполнение, как в этом посте, потому что когда я переключаюсь на long Sensor = 0 Я получаю такие же отрицательные результаты.

Что здесь происходит?

, 👍1


1 ответ


Лучший ответ:

6

abs() определен в Arduino.h как макрос:

 #define abs(x) ((x)>0?(x):-(x))

Макрос не оценивается так же, как функция.

 sensor = abs(analogRead(A0) - 512);

Этот оператор будет расширен во время компиляции до:

 sensor = ((analogRead(A0) - 512)>0?(analogRead(A0) - 512):-(analogRead(A0) - 512));

Теперь «ошибку» понять легко. Аналоговый вывод считывается дважды. «Ошибки» можно избежать, добавив в скетч сначала следующую строку:

#undef abs

Это приведет к удалению макроса abs() и функции стандартной библиотеки вместо этого будет использоваться.

Удачи!

,

Ошибка — макрос abs() в Arduino.h., @Jot

Спасибо за четкий ответ. Я понятия не имел, что макросы вообще существуют в мире Arduino. Я нашел [сообщение](http://forum.arduino.cc/index.php?topic=84364.0) от 2011 года, в котором обсуждался этот и краткий список других макросов. Знаете ли вы окончательный список? Является ли это просто более «ардуинским» подходом и лучшей практикой избегать нескольких присваиваний в строке и придерживаться одной операции в строке?, @Aaron Ciuffo

Нет, использование только одной операции в одном задании не более похоже на Arduino. Иногда это делается для облегчения чтения. Ваша проблема с макросами не имеет большого отношения к Arduino. В более общем плане речь идет о том, как компилятор оценивает макросы. Компилятор заменяет макрос тем, что написано в его определении (и помещает аргумент). Это не функция. И это не специфично для Arduino, а зависит от компилятора. Вы также можете использовать макросы при программировании с помощью других компиляторов. Макросы могут быть полезны, но их следует использовать с осторожностью., @chrisl

@chrisl, функции abs и labs уже есть. Макрос Arduino abs — это нелепая ошибка Arduino. Аарон Чуффо, щелкните ссылку на Arduino.h в ответе Микаэля Пателя, там вы увидите другие макросы. Другое дело — не использовать переменную с именем «B1»., @Jot