Точная калибровка сервоприводов с Arduino UNO и драйвером Adafruit PWM Shield
Компоненты и материалы
| Название | Количество |
|---|---|
| Arduino UNO | 1 |
| Adafruit PWM Servo Driver Shield | 1 |
| Болт M3 | 8 |
| Шайба M3 | 8 |
| DC-DC преобразователь LM2596 (step-down) | 1 |
| PLA пластик красный (для 3D-печати) | 1 |
| PLA пластик белый (для 3D-печати) | 1 |
| Прозрачный транспортир 180° | 1 |
| Потенциометр поворотный | 1 |
| Сервопривод 9g | 1 |
Необходимые инструменты
- 3D-принтер
Приложения и онлайн-сервисы
- Arduino IDE
- Autodesk Fusion 360 (для проектирования корпуса)
О проекте
В предыдущем проекте я сравнивал поведение сервоприводов из одной партии и обнаружил существенные различия: при одинаковом PWM-сигнале они поворачивали на разные углы. На фото видно, как сервоприводы, начав с одной позиции, остановились в разных точках.

Почему не использовать стандартные библиотеки сервоприводов?
Я использую Adafruit PWM Servo Driver, который позволяет управлять множеством сервоприводов по I2C (всего 2 пина), вместо выделения отдельного пина на каждый сервопривод. Кроме того, стандартная библиотека Servo иногда посылает сигнал, заставляющий сервопривод уйти в предельное положение с хрустом шестеренок. Дешевые 9g-сервоприводы не отличаются точностью, но для ходового робота мне нужна большая предсказуемость.
Как управлять хоббийными сервоприводами точнее?
Я построил прибор для калибровки: определить, какие PWM-значения соответствуют углам 0°, 90° и т.д., и избежать значений, вызывающих удар по механизму.
Идея проста:
- Сервопривод устанавливается в центр транспортира, чтобы измерять угол поворота штока.
- Потенциометр подключен к аналоговому входу Arduino — вращая его, я меняю PWM-значение и поворачиваю сервопривод.
- Значения PWM считываются через Serial Monitor и записываются вручную.
Корпус спроектирован в Autodesk 123D (ныне Fusion 360) и содержит потенциометр, транспортир, сервопривод, Arduino, драйвер Adafruit и источник питания.

Сборка прибора
Детали напечатаны на 3D-принтере и собраны на болтах M3 с шайбами. Отверстия под конкретные компоненты — при других габаритах могут потребоваться правки.
Электрика: средний вывод потенциометра — на A0, крайние — на 0V и 5V. Драйвер надевается на Arduino. DC-DC преобразователь настроен на 5В от 9В блока питания. Сервопривод подключен к первому слоту драйвера. Скетч загружен в Arduino.
Вращая ручку потенциометра, я поворачиваю сервопривод и фиксирую PWM-значение из Serial Monitor для каждого угла.


Результаты калибровки
Сервопривод установлен так, что крайнее положение по часовой стрелке соответствует чуть более 180° на транспортире. Я поворачивал потенциометр, совмещая шток с отметками 0°, 10°, 20°… 180°, и записывал PWM. Результаты в таблице и на графике.


Зависимость сильно линейна. Для этого сервопривода формула: PWM = 2.35 × Угол + 159.4.
Теперь есть два варианта точного управления:
- Хранить пары «угол — PWM» в массиве и обращаться к ним (ограничение: только кратно 10°).
- Использовать линейную регрессию: вычислять PWM по формуле для любого угла. Это дает полный контроль.
Калибровка каждого сервопривода требует времени, но для моего проекта точность того стоит. Важно: после снятия сервопривода шток должен оставаться на месте, так как калибровка привязана к его ориентации.
Улучшения для следующей версии
- Быстросъемное крепление сервопривода (магниты вместо болтов).
- Уменьшение размеров (переориентация Arduino и блока питания).
- Выключатель питания между батареей и преобразователем.
- Меньше деталей для печати.
- Автоматическое определение угла датчиком (исключение параллакса).
- LCD-дисплей для автономной работы без ПК.
Заключение
Дешевые хоббийные сервоприводы не точны, но для многих задач этого достаточно. Мой стенд позволяет извлечь из них больше: достичь повторяемой и предсказуемой работы. Это стоит усилий для проектов, требующих точности.
Код
Скетч для калибратора сервоприводов (C/C++)
#include <Adafruit_PWMServoDriver.h>
#define analogIn A0
Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver();
int inputValue = 0;
int tmpPwmValue = 0;
void setup() {
Serial.begin(9600);
pwm.begin();
pwm.setPWMFreq(60);
}
void loop() {
inputValue = analogRead(analogIn); // 0..1024
// Наблюдаемо: min/max PWM обычно 100..612
int pwmValue = (int)(100 + (inputValue / 2));
pwm.setPWM(0, 0, pwmValue);
if (pwmValue != tmpPwmValue) {
Serial.print("Potentiometer Input = ");
Serial.print(inputValue);
Serial.print(", PWM = ");
Serial.println(pwmValue);
}
tmpPwmValue = pwmValue;
delay(15);
}
3D-модели и корпуса
Репозиторий деталей Servo Calibrator
Производственный процесс
- Полилактид (PLA) для 3D-печати: Полное руководство для профессионалов
- Практическое руководство: real-time панорамирование/наклон для отслеживания лиц на Raspberry Pi
- PLA против ABS против нейлона: выбор правильного филамента для 3D-печати
- Walbi: стабильный двухногий робот на Arduino и сервоприводах LX-16A
- Роботизированная рука 5 степеней свободы на Arduino Yun с управлением через Blynk
- PLA против ABS в 3D-печати: Ключевые различия и когда что применять
- Переход на DC приводы: надёжная альтернатива AC сервоприводам в промышленном контроле движения
- PLA: правда ли, что он перерабатываем и биодеградируем?
- Растворяется ли PLA в воде? Условия разложения и способы водостойкости
- Проводит ли PLA электричество? Проводящие варианты и проблемы печати