Промышленное производство
Промышленный Интернет вещей | Промышленные материалы | Техническое обслуживание и ремонт оборудования | Промышленное программирование |
home  MfgRobots >> Промышленное производство >  >> Manufacturing Technology >> Производственный процесс

Превратите любой двигатель постоянного тока в индивидуальный сервопривод на 360° – пошаговое руководство

В этом уроке мы узнаем, как превратить любой двигатель постоянного тока в автономный серводвигатель с множеством функций. В отличие от обычных сервоприводов, которые имеют ограниченное движение в 180 или 270 градусов, этот имеет неограниченный диапазон в 360 градусов, и в дополнение к этому у нас есть возможность регулировать диапазон вращения до любого значения, которое нам нужно.

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

Вы можете посмотреть следующее видео или прочитать письменное руководство ниже.

Другая особенность заключается в том, что мы можем регулировать чувствительность или скорость реакции сервопривода на наш ввод. Говоря о вводе, у нас может быть три разных режима ввода.

Мы можем управлять сервоприводом с помощью аналогового входа напряжения или с помощью потенциометра, мы можем управлять сервоприводом с помощью RC-передатчика, а также управлять сервоприводом через последовательный порт, вводя значения угла через последовательный монитор на нашем ПК или ноутбуке.

Мы также можем делать это одновременно:управлять сервоприводом, вводя значения через последовательный монитор, и вручную перемещать сервопривод с помощью RC-передатчика. Серводвигатель всегда будет знать свое текущее положение и видеть его на последовательном мониторе. 

В верхней части списка функций серводвигателя находится режим непрерывного вращения. Это верно. Мы можем контролировать и отслеживать положение серводвигателя даже в этом режиме непрерывного вращения. Мы можем настроить вал серводвигателя на любое положение с бесконечным количеством оборотов.  

Все это возможно благодаря 12-битному энкодеру, который используется в этом серводвигателе, магнитному датчику положения AS5600 и реализованному ПИД-регулятору для управления двигателем постоянного тока.

Я сделал эту специальную плату контроллера серводвигателя, которая включает в себя собственный микроконтроллер и все остальное, чтобы легко превратить любой двигатель постоянного тока в автономный серводвигатель.

Нам просто нужно расположить плату в центре выходного вала (включая специальный магнит на валу), подключить двигатель постоянного тока любого размера с номинальным током до 3,5 А, запитать всю систему напряжением 12 В и все, мы получаем серводвигатель из обычного двигателя постоянного тока со всеми этими функциями.

Теперь я проведу вас через весь процесс изготовления этого серводвигателя, изготовленного по индивидуальному заказу, чтобы вы могли сделать его самостоятельно. Я объясню принцип работы серводвигателя, регулятора с обратной связью, ПИД-регулятора, как я разработал для него специальную печатную плату и коробку передач, а также объясню код, лежащий в основе этого.

Принцип работы серводвигателя

Чтобы объяснить принцип работы серводвигателя, давайте разберем типичный RC-серводвигатель и посмотрим, что у него внутри.

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

Это типичная установка для большинства радиоуправляемых или любительских серводвигателей. Потенциометр прикреплен к выходному валу двигателя постоянного тока и действует как датчик положения, сообщая контроллеру текущее положение вала серводвигателя. Плата контроллера управляет двигателем постоянного тока на основе входного сигнала (желаемого положения) и фактического положения, которое мы получаем в качестве обратной связи от потенциометра. Это представляет собой замкнутую систему управления.

Входной сигнал или желаемое положение сравнивается с фактическим положением двигателя, которое мы получаем от датчика обратной связи по положению. Возникающая разница, называемая ошибкой, затем обрабатывается контроллером, который дает команду двигателю двигаться до тех пор, пока он не достигнет желаемого положения.

Как сделать собственный серводвигатель

Итак, если мы хотим создать свой собственный серводвигатель с более мощными двигателями постоянного тока, чем те, которые используются в типичных RC-сервоприводах, мы можем реализовать ту же систему управления с обратной связью.

Нам просто нужен датчик положения, каким-то образом прикрепленный к выходному валу, и микроконтроллер для управления двигателем постоянного тока.  

Что касается датчика положения, самое простое решение — использовать простой потенциометр, подобный тому, который мы видели в RC-сервоприводах. Однако проблема с этими типами потенциометров заключается в том, что они имеют ограниченный диапазон вращения - всего 270 градусов, что напрямую ограничивает диапазон вращения серводвигателя. Существуют также другие типы потенциометров, которые могут совершать несколько оборотов и обеспечивать лучший диапазон и разрешение, но при этом имеют ограниченное вращение.

Если нам нужно, чтобы серводвигатель имел неограниченный диапазон вращения, нам нужно использовать энкодер. Энкодеры — это электромеханические устройства, способные отслеживать угловое положение вала при неограниченном вращении. Существует множество типов энкодеров, таких как инкрементные или абсолютные, а также, в зависимости от технологии их считывания, оптические, магнитные или емкостные. Конечно, у каждого из них есть свои преимущества и недостатки.

Кодер AS5600 — магнитный датчик поворотного положения

Я решил использовать магнитный энкодер или магнитный датчик поворотного положения AS5600, поскольку он очень компактен и прост в реализации энкодера, обеспечивающего высокую точность и разрешение. Просто взгляните, какой маленький этот микрочип.

Он имеет встроенный датчик Холла, который может обнаруживать изменения направления магнитного поля. Итак, нам остается лишь прикрепить магнит к выходному валу двигателя и расположить его вблизи микрочипа на расстоянии от 0,5 до 3 мм.

Теперь, когда вал двигателя и магнит будут вращаться, датчик Холла будет фиксировать эти изменения в направлении магнитного поля. С помощью встроенного 12-битного аналого-цифрового преобразователя датчик AS5600 может выдавать 4096 позиций за оборот или вращение на 360 градусов.

Это означает, что он может обнаруживать изменения углового положения всего на 0,0878 градуса. Это довольно впечатляюще, и учитывая тот факт, что он очень доступен и его легко достать, это правильный выбор для серводвигателя, изготовленного по индивидуальному заказу. 

Ладно, что еще нам нужно, микроконтроллер и драйвер двигателя постоянного тока. Я выбрал драйвер двигателя постоянного тока DRV8871, способный выдерживать ток до 3,5 А, и микроконтроллер Atmega328.

Я выбрал версию для поверхностного монтажа, так как она намного компактнее, чем версия DIP, и моей целью было сделать как можно меньше специальной печатной платы, на которой я мог бы разместить все, чтобы сервопривод мог работать как автономное устройство.

Пользовательская принципиальная схема серводвигателя

Вот полная принципиальная схема этого серводвигателя, изготовленного по индивидуальному заказу.

Вы можете получить компоненты, необходимые для этого проекта, по ссылкам ниже:

Раскрытие информации:это партнерские ссылки. Как сотрудник Amazon, я зарабатываю на соответствующих покупках.

Итак, у нас есть микроконтроллер Atmega328 вместе с рекомендуемой минимальной схемой, которая включает в себя генератор с частотой 16 МГц, несколько конденсаторов и резистор.

Для питания микроконтроллера и других компонентов, которым требуется напряжение 5 В, мы используем стабилизатор напряжения AMS1117, который снижает входное напряжение 12 В до 5 В.

Вот датчик положения AS5600 с рекомендуемой схемой, которая включает в себя два конденсатора и два подтягивающих резистора для связи IC2.

Драйверу двигателя постоянного тока DRV8871 требуется всего один резистор для ограничения тока и два развязывающих конденсатора. Затем у нас есть два потенциометра, подключенных к аналоговым входам микроконтроллера:один для регулировки диапазона вращения, а другой для регулировки чувствительности сервопривода. Кнопка используется для установки центральной точки сервопривода, а двухпозиционный переключатель — для выбора режимов работы сервопривода. Имеется разъем для входов сервопривода:либо аналоговый вход напряжения, либо цифровой вход ШИМ от RC-приемника, а также контакт 5 В и заземления. Также имеется разъем для программирования микроконтроллера через протокол SPI и последовательный порт. 

Вот краткий обзор этой схемы и ее рабочего процесса. Входной сигнал или желаемое угловое положение поступает через эти два контакта, и это может быть либо аналоговое напряжение, поступающее от потенциометра, либо цифровой сигнал ШИМ, поступающий от RC-приемника. Входной сигнал поступает в микроконтроллер, где он сравнивается с фактическим угловым положением, обнаруженным энкодером или датчиком положения AS5600. Этот датчик связывается с микроконтроллером по протоколу IC2.

Затем микроконтроллер выполняет математические вычисления, вычисляет ошибку и в соответствии с ней отправляет ШИМ-сигнал драйверу DRV8871, который управляет двигателем постоянного тока до тех пор, пока он не достигнет желаемого положения. 

Вся схема питается от напряжения 12 В, а стабилизатор напряжения AS1117 обеспечивает напряжение 5 В для микроконтроллера и других компонентов соответственно.

Проектирование печатной платы

Судя по принципиальной схеме, я постарался спроектировать печатную плату как можно меньше, и она получилась размером 40х40 мм.

Я располагаю энкодер внизу и точно в центральной точке печатной платы, чтобы его можно было легко установить и совместить с выходным валом сервопривода.

Все остальные компоненты расположены на другой стороне и не мешают работе энкодера и выходного вала.

Я заказал печатную плату в PCBWay. Здесь мы можем просто загрузить файл Gerber, выбрать свойства нашей платы и заказать ее по разумной цене.

Я спроектировал печатную плату так, чтобы она имела 4 слоя, средние предназначены для заземления, что немного увеличивает цену. Я не менял никаких свойств по умолчанию, за исключением цвета печатной платы, который я выбрал белым, и отмечаю, что принимаю изменение отделки поверхности на иммерсионное золото, если применимо, без дополнительной оплаты.

Вы можете найти и загрузить Gerber в сообществе обмена проектами PCBWay, через которое вы также можете напрямую заказать печатную плату.

Тем не менее, через несколько дней пришла печатная плата. Качество печатной платы отличное, все то же самое, что и в дизайне, поверхность мне досталась методом иммерсионного золота.

Отлично, теперь можно переходить к пайке к нему компонентов. Я начал с более мелких компонентов, таких как светодиодный индикатор, конденсаторы и резисторы.

На самом деле я впервые паяю такие маленькие SMD-компоненты, и у меня это очень плохо получалось. 

Сложнее всего было паять микроконтроллер Atmega328, так как выводы действительно маленькие и расположены очень близко друг к другу, но мне как-то удалось это сделать.

Микросхему энкодера AS5600 было легко припаять на задней стороне печатной платы, а также более крупные компоненты со сквозными отверстиями, такие как DIP-переключатель, потенциометры, клеммные колодки и штыревые разъемы.

В любом случае, вот окончательный вид платы контроллера, который, как мне кажется, получился достойным.

Теперь пришло время сделать подходящий редуктор для двигателя постоянного тока и платы контроллера. 

Пользовательская 3D-модель сервопривода

Я спроектировал коробку передач для этого специального серводвигателя с помощью Onshape. Конструкция редуктора, конечно, зависит от двигателя постоянного тока. Как я уже упоминал, мы можем использовать двигатель постоянного тока любого размера в сочетании с только что изготовленной платой контроллера.

Здесь я использую двигатель постоянного тока диаметром 37 мм и встроенный редуктор со скоростью 50 об/мин. 50 об/мин — хорошая скорость для серводвигателя, но я хотел пойти немного ниже, чтобы получить больший крутящий момент, поэтому я сделал коробку передач с трехкратным уменьшением. Для этой цели я использовал шестеренки в виде елочки, поскольку их удобно и легко изготовить на 3D-принтере.

Конечно, здесь у нас есть свобода создавать конструкцию коробки передач по своему усмотрению, поскольку это зависит от двигателя постоянного тока, который мы хотим использовать, и от того, какую выходную скорость мы хотим получить. 

Я разместил плату контроллера на задней стороне коробки передач и идеально выровнял ее по центру выходного вала.

Если мы хотим использовать вал двигателя постоянного тока непосредственно в качестве выхода, мы можем просто использовать зубчатую передачу 1:1, чтобы мы могли правильно отслеживать положение вала. Или в таком случае мы могли бы также использовать ременную систему. Как я уже сказал, у нас есть безграничные возможности для изготовления коробки передач. 

Загрузите 3D-модель и файлы STL

Вы можете просмотреть и изучить 3D-модель этого изготовленного по индивидуальному заказу серводвигателя прямо в веб-браузере с помощью Onshape. (Для этого вам понадобится учетная запись Onshape. Вы можете создать бесплатную учетную запись для домашнего использования)

Конечно, вы также загружаете 3D-модель, а также файлы STL, необходимые для 3D-печати деталей, отсюда:

ШАГОВЫЙ файл:

Файлы STL для 3D-печати:

Сборка пользовательского сервопривода

Вот напечатанные на 3D-принтере детали для этой сборки, чтобы мы могли приступить к сборке серводвигателя.

Вместе с ними нам понадобятся болты М3 и резьбовые вставки, а также подшипники. 

Сначала я прикрепил двигатель постоянного тока к опорной пластине с помощью болтов М3 длиной 8 мм.

Затем мы можем установить две шестерни на место. Меньшая шестерня идет непосредственно на вал двигателя постоянного тока, а большая шестерня будет выходом сервопривода. Однако выходной вал состоит из двух частей.

С обеих сторон этой части выходного вала я установил резьбовые вставки, с одной стороны для подключения к ней шестерни, а с другой стороны для крепления вещей на выходе сервопривода. 

Я также установил резьбовые вставки на меньшую шестерню, которая будет использоваться для ее крепления к валу двигателя постоянного тока. Теперь мы можем вставить спаренные шестерни на место. Поскольку это шестерни «елочкой», мы должны вставить их обе на место одновременно, иначе мы не сможем соединить их, если вставим их одну за другой.

С помощью установочного винта я закрепил маленькую шестерню на валу двигателя постоянного тока. Я подал напряжение 12 В на двигатель постоянного тока, чтобы проверить, будет ли работать редуктор. 

Мы можем завершить сборку коробки передач, вставив боковую панель, шарикоподшипник выходного вала и верхнюю крышку.

Я установил несколько вставок с резьбой М3 на заднюю пластину, чтобы мы могли закрепить всю сборку болтами М3 длиной 20 мм. Проверил еще раз коробку передач, работает отлично. Мы можем заметить, как выходной вал вращается с обратной стороны, и здесь нам нужно вставить магнит, за которым будет следить энкодер AS5600.

Прикрепляем плату контроллера к коробке передач с помощью болтов и гаек М2. Датчик положения AS5600 теперь идеально совмещен с магнитом, поэтому при вращении выходного вала он правильно измеряет изменение магнитного поля.

Обратите внимание, что направление намагничивания постоянного магнита очень важно. В зависимости от того, намагничивается ли он аксиально или диаметрально, мы должны расположить магнит перпендикулярно или параллельно этой микросхеме AS5600.

В итоге мне пришлось изменить направление магнита, так как у него не было нужной намагниченности, чтобы энкодер AS5600 мог ее измерить.

Далее я припаял два провода к двигателю постоянного тока и подключил двигатель к контроллеру с помощью клеммной колодки. Что касается питания, то я подключил два провода к клеммной колодке питания, на другой стороне которой имеется разъем питания постоянного тока для подключения источника питания 12 В. Вот и все, наш изготовленный по индивидуальному заказу серводвигатель готов.

Программирование контроллера

Теперь осталось дать жизнь этому сервоприводу или запрограммировать контроллер. Для этого сначала нам нужно записать загрузчик в микроконтроллер ATmega328p. Без загрузчика микроконтроллер не сможет понять язык или код, который мы ему отправим. 

Запись загрузчика

Чтобы записать загрузчик на ATmega328p, нам понадобится плата Arduino, в моем случае я буду использовать плату Arduino Nano.

Мы будем использовать связь SPI, поэтому нам нужно соединить подходящие контакты SPI на плате Arduino и плате контроллера.

Теперь, используя Arduino IDE, нам нужно открыть пример скетча ArduinoISP и загрузить его на плату Arduino Nano. С помощью этого кода Arduino Nano теперь может записать загрузчик в микроконтроллер ATmega328. 

Далее в меню «Инструменты» нам как программисту нужно выбрать Arduino в качестве интернет-провайдера и затем нажать «Записать загрузчик».

Во время записи загрузчика мы должны заметить, что индикаторы Arduino NANO будут часто мигать, что приведет к успешной записи загрузчика. 

Загрузка кода

Как только мы закончим с этим, теперь мы можем запрограммировать или загрузить код на плату контроллера с помощью модуля интерфейса USB-UART.

На плате контроллера имеются специальные контакты для их удобного подключения, как показано на этой принципиальной схеме. 

Теперь мы можем открыть код этого специально созданного мной сервопривода и загрузить его в контроллер. Однако прежде чем мы это сделаем, нам следует сначала установить библиотеки для датчика AS5600 и ПИД-регулирования. Мы можем легко сделать это с помощью диспетчера библиотек Arduino IDE. Как только мы нажмем кнопку загрузки, код будет записан в наш контроллер ATmega328 через модуль интерфейса USB-UART.

Вот и все, наш индивидуальный серводвигатель готов. Теперь мы можем подключить к нему потенциометр, чтобы проверить его. Обратите внимание, что аналоговый вход подключается к контакту «S» на плате контроллера, а не к контакту «A».

При проектировании печатной платы я неправильно подключил эти два контакта к ATmega328. Затем мы можем выбрать режим аналогового входа с помощью DIP-переключателя и подать питание на сервопривод.

И вот мы можем управлять положением серводвигателя с помощью аналогового входа потенциометра. Мы успешно преобразовали наш двигатель постоянного тока в серводвигатель.

Исходный код

Теперь давайте взглянем на код этого специально созданного серводвигателя.

/*
 * Custom-built Servo Motor - Arduino Code
 * by Dejan, www.HowToMechatronics.com
 * 
 * Libraries:
 * AS5600 encoder: https://github.com/RobTillaart/AS5600
 * PID conroller: https://github.com/br3ttb/Arduino-PID-Library/blob/master/PID_v1.h
 */
#include "AS5600.h"
#include "Wire.h"
#include <PID_v1.h>
AS5600 as5600; // use default Wire
double Pk1 = 2; //speed it gets there
double Ik1 = 0;
double Dk1 = 0.025;
//Define Variables we'll be connecting to
double Setpoint, Input, Output;
PID myPID(&Input, &Output, &Setpoint, Pk1, Ik1, Dk1, DIRECT);
#define motor_IN1 5
#define motor_IN2 6
#define ch1 2
#define centerSet 7
#define inputSwitch 3
#define modeSwitch 4
int ch1Value;
int encoderValue, inputValue, pwmValue;
String inString = ""; // string to hold input
int centerAngle = 2047; // 180 degrees
int angleDifference = 0;
int angleValue = 0;
int leftLimit = 30;
int rightLimit = 4067;
int rangeAdjustment = 0;
float sensitivityAdjustment = 0;
float angle = 0;
int quadrantNumber = 2;
int previousQuadrantNumber = 3;
int numberOfTurns = 0;
float totalAngle = 0;
int error = 0;
char incomingByte = 0;
int intInput = 0;
void setup() {
 Serial.begin(115200);
 Serial.println(__FILE__);
 Serial.print("AS5600_LIB_VERSION: ");
 Serial.println(AS5600_LIB_VERSION);
 Wire.begin();
 pinMode(motor_IN1, OUTPUT);
 pinMode(motor_IN2, OUTPUT);
 // Activate the Arduino internal pull-up resistors
 pinMode(centerSet, INPUT_PULLUP);
 pinMode(inputSwitch, INPUT_PULLUP);
 pinMode(4, INPUT_PULLUP);
 myPID.SetMode(AUTOMATIC); // PID Setup
 myPID.SetOutputLimits(-255, 255);
 myPID.SetSampleTime(20);
}
void loop() {
 // Read encoder value - current position
 encoderValue = as5600.readAngle();
 // Continuous rotation mode
 if (digitalRead(modeSwitch) == 0) {
 // Enter desired angle for the servo to go to through the serial monitor
 while (Serial.available() > 0) {
 int inChar = Serial.read();
 if (isDigit(inChar)) {
 // convert the incoming byte to a char and add it to the string:
 inString += (char)inChar;
 }
 // if you get a newline, print the string, then the string's value:
 if (inChar == '\n') {
 Setpoint = inString.toInt(); // Setpoint - desired angle
 // clear the string for new input:
 inString = "";
 }
 }
 if (digitalRead(inputSwitch) == 0) { // Potentiometer as input
 inputValue = analogRead(A0);
 if (inputValue < 400) {
 Setpoint = Setpoint - 0.3;
 }
 if (inputValue < 300) {
 Setpoint = Setpoint - 0.3;
 }
 if (inputValue < 200) {
 Setpoint = Setpoint - 0.3;
 }
 if (inputValue > 600) {
 Setpoint = Setpoint + 0.3;
 }
 if (inputValue > 700) {
 Setpoint = Setpoint + 0.3;
 }
 if (inputValue > 800) {
 Setpoint = Setpoint + 0.3;
 }
 }
 else if (digitalRead(inputSwitch) == 1) {
 inputValue = pulseIn(ch1, HIGH, 30000); // RC receiver as input
 if (inputValue < 1450) {
 Setpoint--;
 }
 if (inputValue < 1350) {
 Setpoint--;
 }
 if (inputValue < 1250) {
 Setpoint--;
 }
 if (inputValue < 1150) {
 Setpoint--;
 }
 if (inputValue > 1550) {
 Setpoint++;
 }
 if (inputValue > 1650) {
 Setpoint++;
 }
 if (inputValue > 1750) {
 Setpoint++;
 }
 if (inputValue > 1850) {
 Setpoint++;
 }
 }
 // Convert encoder RAW values into angle value
 angle = encoderValue * 0.087890625;
 // Quadrant 1
 if (angle >= 0 && angle <= 90) {
 quadrantNumber = 1;
 }
 // Quadrant 2
 if (angle >= 90 && angle <= 180) {
 quadrantNumber = 2;
 }
 // Quadrant 3
 if (angle >= 180 && angle <= 270) {
 quadrantNumber = 3;
 }
 // Quadrant 4
 if (angle >= 270 && angle <= 360) {
 quadrantNumber = 4;
 }
 if (quadrantNumber != previousQuadrantNumber) {
 // Transition from 4th to 1st quadrant
 if (quadrantNumber == 1 && previousQuadrantNumber == 4) {
 numberOfTurns++;
 }
 // Transition from 1st to 4th quadrant
 if (quadrantNumber == 4 && previousQuadrantNumber == 1) {
 numberOfTurns--;
 }
 previousQuadrantNumber = quadrantNumber;
 }
 if (totalAngle >= 0) {
 totalAngle = (numberOfTurns * 360) + angle;
 }
 else {
 totalAngle = (numberOfTurns * 360) + angle;
 }
 // Establish Input value for PID
 Input = totalAngle;
 }
 // Limited Rotation Mode
 else if (digitalRead(modeSwitch) == 1) {
 rangeAdjustment = analogRead(A1);
 leftLimit = 0 + 30 + rangeAdjustment;
 rightLimit = 4097 - 30 - rangeAdjustment;
 if (digitalRead(inputSwitch) == 0) { // Analog input - Potentiometer
 // Get value from potentiometer
 inputValue = analogRead(A0);
 if (inputValue < 15) {
 inputValue = 15;
 }
 if (inputValue > 1008) {
 inputValue = 1008;
 }
 Setpoint = map(inputValue, 15, 1008, -255, 255);
 }
 else if (digitalRead(inputSwitch) == 1) { // Digital input - RC transmitter
 inputValue = pulseIn(ch1, HIGH, 30000); // Read RC receiver as input
 Setpoint = map(inputValue, 1000, 2000, -255, 255);
 }
 // Set center angle
 if (digitalRead(centerSet) == LOW) {
 centerAngle = encoderValue;
 angleDifference = 2047 - encoderValue;
 delay(1000);
 }
 // Adjust angle value according to the center point (angleDifference)
 if (centerAngle < 2047) {
 angleValue = encoderValue + angleDifference;
 if (encoderValue < 4097 && encoderValue > (4096 - angleDifference)) {
 angleValue = encoderValue - 4097 + angleDifference;
 }
 }
 if (centerAngle > 2047) {
 angleValue = encoderValue + angleDifference;
 if (encoderValue >= 0 && encoderValue < abs(angleDifference)) {
 angleValue = encoderValue + 4097 + angleDifference;
 }
 }
 else if (centerAngle == 2047) {
 angleValue = encoderValue;
 }
 // Establish Input value for PID
 Input = map(angleValue , leftLimit, rightLimit, -255, 255);
 }
 // Adjusting sensitivity
 Pk1 = analogRead(A2) * 0.002;
 myPID.SetTunings(Pk1, Ik1, Dk1);
 // Run PID process to get Output value
 myPID.Compute();
 // Move right
 if (Output > 1 ) {
 pwmValue = Output;
 if (pwmValue < 30 && pwmValue > 5) {
 pwmValue = pwmValue + 30;
 }
 if (pwmValue <= 5) {
 pwmValue = 0;
 }
 digitalWrite(motor_IN1, LOW);
 analogWrite(motor_IN2, pwmValue);
 }
 // Move left
 else if (Output < 1 ) {
 pwmValue = abs(Output);
 if (pwmValue < 30 && pwmValue > 5) {
 pwmValue = pwmValue + 30;
 }
 if (pwmValue <= 5) {
 pwmValue = 0;
 }
 analogWrite(motor_IN1, pwmValue);
 digitalWrite(motor_IN2, LOW);
 }
 // Do not move
 else if (Output > -1 && Output < 1) {
 pwmValue = 0;
 digitalWrite(motor_IN1, LOW);
 digitalWrite(motor_IN2, LOW);
 }
 //Serial.print(Setpoint);
 //Serial.print("\t");
 //Serial.println(totalAngle);
}Code language: PHP (php)

Обзор кода

Итак, мы начинаем цикл со считывания значения энкодера или текущего положения вала.

// Read encoder value - current position
 encoderValue = as5600.readAngle();Code language: JavaScript (javascript)

Затем, если мы находимся в режиме непрерывного вращения, мы принимаем значения от последовательного монитора и используем их в качестве заданного значения или желаемого угла для ПИД-регулятора.

// Enter desired angle for the servo to go to through the serial monitor
 while (Serial.available() > 0) {
 int inChar = Serial.read();
 if (isDigit(inChar)) {
 // convert the incoming byte to a char and add it to the string:
 inString += (char)inChar;
 }
 // if you get a newline, print the string, then the string's value:
 if (inChar == '\n') {
 Setpoint = inString.toInt(); // Setpoint - desired angle
 // clear the string for new input:
 inString = "";
 }
 }Code language: JavaScript (javascript)

Если режим входа установлен на потенциометр, мы считываем его аналоговый вход и корректируем заданное значение в зависимости от того, насколько далеко мы его поворачиваем.

if (digitalRead(inputSwitch) == 0) { // Potentiometer as input
 inputValue = analogRead(A0);
 if (inputValue < 400) {
 Setpoint = Setpoint - 0.3;
 }
 if (inputValue < 300) {
 Setpoint = Setpoint - 0.3;
 }
 if (inputValue < 200) {
 Setpoint = Setpoint - 0.3;
 }
 if (inputValue > 600) {
 Setpoint = Setpoint + 0.3;
 }
 if (inputValue > 700) {
 Setpoint = Setpoint + 0.3;
 }
 if (inputValue > 800) {
 Setpoint = Setpoint + 0.3;
 }
 }Code language: JavaScript (javascript)

Мы делаем ту же самую коррекцию уставки, если входом является RC-приемник. 

Здесь мы конвертируем значения энкодера RAW в значения углов и с помощью этих операторов if отслеживаем, в каком квадранте находится текущее положение вала.

// Convert encoder RAW values into angle value
 angle = encoderValue * 0.087890625;
 // Quadrant 1
 if (angle >= 0 && angle <= 90) {
 quadrantNumber = 1;
 }
 // Quadrant 2
 if (angle >= 90 && angle <= 180) {
 quadrantNumber = 2;
 }
 // Quadrant 3
 if (angle >= 180 && angle <= 270) {
 quadrantNumber = 3;
 }
 // Quadrant 4
 if (angle >= 270 && angle <= 360) {
 quadrantNumber = 4;
 }Code language: HTML, XML (xml)

Имея эту информацию, мы можем отслеживать, как вращается вал и когда он сделает полный оборот. Общий угол — это входное значение для ПИД-регулятора.

if (quadrantNumber != previousQuadrantNumber) {
 // Transition from 4th to 1st quadrant
 if (quadrantNumber == 1 && previousQuadrantNumber == 4) {
 numberOfTurns++;
 }
 // Transition from 1st to 4th quadrant
 if (quadrantNumber == 4 && previousQuadrantNumber == 1) {
 numberOfTurns--;
 }
 previousQuadrantNumber = quadrantNumber;
 }
 if (totalAngle >= 0) {
 totalAngle = (numberOfTurns * 360) + angle;
 }
 else {
 totalAngle = (numberOfTurns * 360) + angle;
 }
 // Establish Input value for PID
 Input = totalAngle;Code language: JavaScript (javascript)

С другой стороны, если мы находимся в режиме ограниченного вращения, сначала мы считываем значение потенциометра, которое используется для регулировки диапазона вращения, и соответственно регулируем левый и правый предел вращения.

rangeAdjustment = analogRead(A1);
 leftLimit = 0 + 30 + rangeAdjustment;
 rightLimit = 4097 - 30 - rangeAdjustment;

Если режимом входа является потенциометр, мы используем его значение в качестве значения уставки для ПИД-регулятора.

if (digitalRead(inputSwitch) == 0) { // Analog input - Potentiometer
 // Get value from potentiometer
 inputValue = analogRead(A0);
 if (inputValue < 15) {
 inputValue = 15;
 }
 if (inputValue > 1008) {
 inputValue = 1008;
 }
 Setpoint = map(inputValue, 15, 1008, -255, 255);
 }Code language: HTML, XML (xml)

Если режимом ввода является RC-приемник, мы считываем входящее значение ШИМ с приемника и используем это значение в качестве заданного значения.

else if (digitalRead(inputSwitch) == 1) { // Digital input - RC transmitter
 inputValue = pulseIn(ch1, HIGH, 30000); // Read RC receiver as input
 Setpoint = map(inputValue, 1000, 2000, -255, 255);
 }Code language: JavaScript (javascript)

Чтобы установить другую центральную точку, мы проверяем, нажали ли мы кнопку, и фиксируем это положение как новую центральную точку.

// Set center angle
 if (digitalRead(centerSet) == LOW) {
 centerAngle = encoderValue;
 angleDifference = 2047 - encoderValue;
 delay(1000);
 }Code language: JavaScript (javascript)

Согласно ему, нам предстоит корректировать фактические показания энкодера и смещать их на разницу углов между новой и старой центральной точкой. Мы используем это значение в качестве входного значения для ПИД-регулятора.

if (centerAngle > 2047) {
 angleValue = encoderValue + angleDifference;
 if (encoderValue >= 0 && encoderValue < abs(angleDifference)) {
 angleValue = encoderValue + 4097 + angleDifference;
 }
 }
 else if (centerAngle == 2047) {
 angleValue = encoderValue;
 }
 // Establish Input value for PID
 Input = map(angleValue , leftLimit, rightLimit, -255, 255);Code language: HTML, XML (xml)

Используя аналоговый вход от другого потенциометра, мы регулируем пропорциональное усиление ПИД-регулятора и, наконец, запускаем ПИД-процесс, чтобы получить выходное значение.

// Adjusting sensitivity
 Pk1 = analogRead(A2) * 0.002;
 myPID.SetTunings(Pk1, Ik1, Dk1);
 // Run PID process to get Output value
 myPID.Compute();Code language: JavaScript (javascript)

Мы используем это выходное значение для управления двигателями постоянного тока с помощью ШИМ-сигнала, влево или вправо, или в неподвижном положении, в зависимости от выходного значения ПИД-регулятора или в зависимости от ошибки между желаемым и фактическим положением, считываемым энкодером.

// Move right
 if (Output > 1 ) {
 pwmValue = Output;
 if (pwmValue < 30 && pwmValue > 5) {
 pwmValue = pwmValue + 30;
 }
 if (pwmValue <= 5) {
 pwmValue = 0;
 }
 digitalWrite(motor_IN1, LOW);
 analogWrite(motor_IN2, pwmValue);
 }Code language: HTML, XML (xml)

Вот и все в этом видео. Обратите внимание, что код недостаточно оптимизирован и его можно улучшить.

Кроме того, если вы попытаетесь воссоздать этот проект, вы должны быть готовы к устранению неполадок. Есть много вещей, которые могут пойти не так, особенно при пайке небольших SMD-компонентов.

У меня этот сервопривод не заработал с первого раза. Первоначально у меня были неправильные соединения на печатной плате, затем я снова заказал печатную плату с новыми обновлениями, но мне потребовалось еще несколько попыток, прежде чем она заработала. 

Этот раздел статьи все еще находится в разработке, пожалуйста, проверьте его чуть позже….


Производственный процесс

  1. Что такое мини-сверлильный станок?
  2. Как анодируется алюминиевый металл
  3. Ультразвуковой датчик HC-SR04 и Arduino — полное руководство
  4. Различные виды металлов и их классификация
  5. Как сокращение субсидий влияет на отрасль аккумуляторных батарей
  6. Объяснение свойств и сортов серого чугуна
  7. Детали из алюминия и нержавеющей стали для аэрокосмического применения
  8. Создайте высокопроизводительный радиоуправляемый танк с двухскоростной коробкой передач, напечатанный на 3…
  9. Электронные водяные насосы в автомобильной промышленности
  10. Временная татуировка