constrain()
constrain(x, a, b) «зажимает» число в диапазоне [a, b]: возвращает x как есть или ближайшую границу — удобно для ограничения сигналов датчиков без лишних if.
Полная статья
Описание
constrain() — простая, но очень полезная функция: она «зажимает» значение между нижней и верхней границами. Если число попадает в диапазон, оно возвращается без изменений. Если оно меньше минимума — вернётся минимум. Если больше максимума — вернётся максимум.
Типичный пример: вы читаете показания датчика и передаёте их в функцию управления мотором или сервоприводом. Физически мотор не может выйти за пределы своего диапазона движения, поэтому имеет смысл заранее ограничить входное значение, не загромождая код условными операторами if.
Синтаксис
constrain(x, a, b)
Параметры
x— число, которое нужно ограничить. Принимается любой тип данных.a— нижняя граница диапазона. Принимается любой тип данных.b— верхняя граница диапазона. Принимается любой тип данных.
Возвращаемое значение
x— еслиxнаходится междуaиbвключительно.a— еслиxменьшеa.b— еслиxбольшеb.
Другими словами, результат всегда лежит в диапазоне [a, b].
Пример кода
Код задаёт тестовое значение, имитирующее показание датчика, ограничивает его диапазоном и выводит результат в Serial Monitor.
int sensVal = 50; // попробуй со значениями 170 и 5, чтобы проверить работу
void setup() {
Serial.begin(9600);
sensVal = constrain(sensVal, 10, 150); // ограничивает диапазон значений датчика от 10 до 150
Serial.print("The sensor value is: ");
Serial.println(sensVal);
}
void loop() {
}
Где применяется
- Управление сервоприводом или мотором — чтобы не передавать значения за пределами допустимого угла или скорости.
- Обработка данных с аналогового датчика — например, ограничить
analogRead()диапазоном, который реально используется в вашей схеме. - Интерфейс пользователя — удержать значение счётчика кнопок или энкодера в пределах меню.
- Вычисления с ПИД-регулятором — ограничить выходной сигнал регулятора, чтобы он не выходил за физические пределы исполнительного устройства.
Практические замечания
constrain()работает с любым числовым типом:int,float,longи другими. Следите за тем, чтобы типыx,aиbбыли совместимы, иначе возможны неочевидные приведения типов.- Функция реализована как макрос, а не как обычная функция. Из-за этого передача в аргументы выражений с побочными эффектами — вызовов функций, инкремента и т. п. — может привести к тому, что выражение вычислится несколько раз и даст неожиданный результат.
- Этот код может дать неожиданные результаты, потому что выражение внутри
constrain()может быть вычислено больше одного раза:
int constrainedInput = constrain(Serial.parseInt(), minimumValue, maximumValue); // избегай этого
- Правильный подход — сначала сохранить результат в переменную, а потом передать её в
constrain():
int input = Serial.parseInt(); // выполняй другие операции за пределами функции constrain
int constrainedInput = constrain(input, minimumValue, maximumValue);
- Если
aбольшеb, поведение функции не определено — всегда передавайте границы в правильном порядке: сначала меньшее, потом большее. constrain()не заменяет проверку входных данных в критически важном коде: она молча «обрезает» значение, не сообщая о том, что оно вышло за границы. Если вам важно знать о выходе за пределы — добавьте явную проверку рядом.
Примечания и предупреждения
Из-за того, как реализована constrain(), избегайте передачи вызовов функций прямо внутрь её аргументов — это может привести к неверным результатам.