Convierte Cualquier Motor DC en un Servo Personalizado de 360° – Guía Paso a Paso
En este tutorial aprenderemos a convertir cualquier motor DC en un servo motor personalizado independiente con muchas funciones. A diferencia de los servos normales con rango limitado de 180° o 270°, este tiene rango ilimitado de 360° y, además, podemos ajustar el rango de rotación a cualquier valor que necesitemos.
Eso es muy útil, y encima podemos ajustar el punto central del servo. Así que podemos ajustar tanto el centro como el rango de rotación a la vez.
Puedes ver el siguiente vídeo o leer el tutorial escrito a continuación.
Otra función es ajustar la sensibilidad o rapidez de respuesta del servo. Sobre la entrada, tenemos tres modos distintos.
Podemos controlar el servo con entrada analógica de tensión o potenciómetro, con un transmisor RC, o mediante puerto serie introduciendo valores de ángulo en el Monitor Serie de nuestro PC o portátil.
Incluso podemos hacerlo simultáneamente: controlar el servo introduciendo valores por el Monitor Serie y moverlo manualmente con el transmisor RC. El servo conoce su posición actual en todo momento y la vemos en el Monitor Serie.
Y la guinda: modo rotación continua. Sí, podemos controlar y rastrear la posición del servo incluso en rotación continua. Podemos ordenar al eje que vaya a cualquier posición con un número infinito de vueltas.
Todo esto es posible gracias al encoder de 12 bits que emplea, el sensor magnético rotativo AS5600, y el control PID implementado para pilotar el motor DC.
Hice esta placa controladora de servo personalizada que incluye su propio microcontrolador y todo lo necesario para convertir fácilmente cualquier motor DC en un servo independiente.
Solo hay que colocar la placa en el centro del eje de salida (incluyendo un imán específico en el eje), conectar cualquier motor DC de hasta 3,5 A nominal, alimentar todo con 12 V y listo: tenemos un servo motor a partir de un motor DC normal con todas estas funciones.
Ahora te guiaré por todo el proceso de fabricación de este servo personalizado para que tú también puedas hacer uno. Explicaré el principio de funcionamiento de un servo motor, un controlador de lazo cerrado, un controlador PID, cómo diseñé el PCB y la caja de engranajes, y el código detrás de todo.
Principio de Funcionamiento de un Servo Motor
Para explicar el principio, desmontemos un servo RC típico y veamos qué hay dentro.
Vemos que tiene un pequeño motor DC, una placa controladora, un potenciómetro y conexión de tres hilos: dos para alimentación y uno para señal de entrada. También hay engranajes para reducir velocidad y aumentar par del motor DC.
Es la configuración típica de la mayoría de servos RC o de hobby. El potenciómetro va unido al eje de salida del motor y actúa como sensor de posición, indicando al controlador la posición actual del eje. La placa controla el motor basándose en la señal de entrada (posición deseada) y la posición real que retroalimenta el potenciómetro. Esto representa un sistema de control de lazo cerrado.
La señal de entrada (posición deseada) se compara con la posición real del motor que obtenemos del sensor de retroalimentación. La diferencia (error) se procesa en el controlador, que manda al motor moverse hasta alcanzar la posición deseada.
Cómo Hacer un Servo Motor Personalizado
Así que, si queremos construir nuestro propio servo con motores DC más grandes que los servos RC típicos, podemos implementar el mismo sistema de lazo cerrado.
Solo necesitamos un sensor de posición unido al eje de salida de alguna forma y un microcontrolador para pilotar el motor DC.
Como sensor de posición, la solución más simple es un potenciómetro como el de los servos RC. El problema es que su rango de rotación se limita a 270°, lo que limita directamente el rango del servo. Hay potenciómetros multivuelta con mayor rango y resolución, pero siguen teniendo rotación limitada.
Si necesitamos rango ilimitado, debemos usar un encoder. Los encoders son dispositivos electromecánicos que rastrean la posición angular del eje con rotación ilimitada. Hay muchos tipos: incrementales o absolutos, o según tecnología: ópticos, magnéticos, capacitivos. Cada uno tiene ventajas e inconvenientes.
Encoder AS5600 – Sensor Magnético Rotativo de Posición
Elegí un encoder magnético, el AS5600, porque es muy compacto, fácil de implementar y ofrece alta preción/resolución. Fíjate qué pequeño es este microchip.
Tiene un sensor Hall integrado que detecta cambios en la dirección del campo magnético. Solo hay que pegar un imán al eje de salida del motor y colocarlo cerca del chip a 0,5–3 mm.
Al girar el eje y el imán, el sensor Hall captura esos cambios en la dirección del campo. Con su conversor A/D de 12 bits integrado, el AS5600 entrega 4096 posiciones por vuelta (360°).
Eso significa que detecta cambios de posición angular tan pequeños como 0,0878°. Muy impresionante, y al ser barato y fácil de conseguir, es la elección correcta para un servo personalizado.
¿Qué más hace falta? Un microcontrolador y un driver para el motor DC. Elegí el driver DRV8871 (hasta 3,5 A) y el microcontrolador Atmega328.
Elegí la versión SMD del Atmega328, mucho más compacta que la DIP, porque mi objetivo era hacer el PCB personalizado lo más pequeño posible e incluir todo para que el servo funcione como dispositivo independiente.
Diagrama de Circuito del Servo Personalizado
Aquí tienes el esquema completo de este servo personalizado.
Puedes conseguir los componentes en los enlaces:
- Encoder magnético AS5600 ………………….. Amazon / AliExpress
- Driver DC DRV8871 ……………….…. Amazon / AliExpress
- Atmega328p-AU …………………………………. Amazon / AliExpress
- Oscilador de cristal 16 MHz …………………….. Amazon / AliExpress
- Regulador AMS1117 5V ………..…. Amazon / AliExpress
- Potenciómetro multivuelta 3386P ………………. Amazon / AliExpress
- Kit condensadores 0805 …………………………….…. Amazon / AliExpress
- Motor DC 12V – ~50 RPM …………….……. Amazon / AliExpress
Nota: Son enlaces de afiliado. Como asociado de Amazon gano por compras que califiquen.
Tenemos el Atmega328 con su circuito mínimo recomendado: oscilador 16 MHz, pocos condensadores y una resistencia.
Para alimentar el micro y componentes de 5 V usamos el regulador AMS1117, que baja los 12 V de entrada a 5 V.
Aquí está el AS5600 con su circuito recomendado: dos condensadores y dos resistencias pull-up para comunicación I2C.
El DRV8871 necesita una resistencia para limitar corriente y dos condensadores de desacople. Luego tenemos dos potenciómetros en entradas analógicas del micro: uno para ajustar rango de rotación y otro para sensibilidad. El pulsador sirve para definir el punto central, y el DIP switch de dos vías para seleccionar modos de funcionamiento. Hay un pin header para entradas del servo (tensión analógica o PWM digital de receptor RC), con 5 V y GND. También hay pin header para programar el micro vía SPI y puerto serie.
Resumen del circuito y flujo de trabajo: la entrada (posición angular deseada) llega por esos dos pines y puede ser tensión analógica de potenciómetro o PWM digital de receptor RC. La entrada entra al micro, donde se compara con la posición angular real detectada por el encoder AS5600 (comunicación I2C). El micro calcula el error y, según este, envía PWM al DRV8871 que pilota el motor hasta alcanzar la posición deseada.
Todo el circuito se alimenta a 12 V, y el AMS1117 da 5 V para el micro y demás componentes.
Diseño del PCB
Según el esquema, intenté hacer el PCB lo más pequeño posible: salió 40 × 40 mm.
Puse el encoder en la cara inferior y exactamente en el centro del PCB, para montarlo y alinearlo fácil con el eje de salida del servo.
Todos los demás componentes están en la otra cara para no interferir con el encoder y el eje.
Pedí el PCB a PCBWay. Subes el Gerber, eliges propiedades y lo pides a precio razonable.
Diseñé el PCB a 4 capas, las intermedias para GND, lo que sube un poco el precio. No cambié propiedades por defecto salvo color blanco, y marqué aceptar cambio de acabado a oro por inmersión si aplica sin cargo extra.
Puedes encontrar y descargar el Gerber en la comunidad de proyectos compartidos de PCBWay, desde donde también puedes pedirlo directamente.
Tras unos días llegó el PCB. Calidad estupenda, todo idéntico al diseño, y me llegó con acabado oro por inmersión.
Ahora soldamos componentes. Empecé por los pequeños: LED indicador, condensadores, resistencias.
Es mi primera vez soldando componentes SMD tan pequeños, y lo hice muy mal.
Lo más difícil fue soldar el Atmega328, con pines muy juntos, pero logré hacerlo.
El AS5600 en la cara trasera fue fácil, igual que los componentes through-hole mayores: DIP switch, potenciómetros, bornes, pin headers.
Así quedó la placa controladora, que al final resultó decente.
Ahora toca hacer una caja de engranajes adecuada para el motor DC y esta placa.
Modelo 3D del Servo Personalizado
Diseñé la caja de engranajes para este servo usando Onshape. El diseño depende del motor DC. Como dije, podemos usar cualquier motor DC con la placa controladora que acabamos de hacer.
Aquí uso un motor DC de 37 mm de diámetro con reductor integrado que da 50 RPM. 50 RPM está bien para un servo, pero quería ir un poco más bajo para más par, así que hice una caja con reducción 3:1. Usé engranajes espiga (herringbone) porque son eficientes y fáciles de imprimir en 3D.
Por supuesto, aquí tenemos libertad total para diseñar la caja como queramos, según el motor y la velocidad de salida deseada.
Coloqué la placa controladora en la parte trasera de la caja, alineada perfectamente con el centro del eje de salida.
Si queremos usar el eje del motor directamente como salida, usamos engranajes 1:1 para rastrear la posición correctamente. O podríamos usar sistema de correa. Como dije, hay infinitas posibilidades.
Descarga Modelo 3D y Archivos STL
Puedes ver y explorar el modelo 3D de este servo personalizado en tu navegador con Onshape (necesitas cuenta Onshape, puedes crear una gratis para uso doméstico).
Por supuesto, también puedes descargar el modelo 3D y los archivos STL para imprimir las piezas desde aquí:
Archivo STEP:
Archivos STL para impresión 3D:
Montaje del Servo Personalizado
Aquí están las piezas impresas para empezar a montar el servo.
Junto con ellas hacen falta tornillos M3, insertos roscados y rodamientos.
Primero fijé el motor DC a la placa base con tornillos M3 de 8 mm.
Luego instalamos los dos engranajes. El pequeño va directo al eje del motor, el grande será la salida del servo. El eje de salida se compone de dos partes.
Puse insertos roscados en ambos lados de esta pieza de eje: un lado para unir el engranaje, el otro para acoplar cosas en la salida. También puse insertos en el engranaje pequeño para fijarlo al eje del motor. Ahora deslizamos los engranajes emparejados. Al ser espiga, hay que meterlos a la vez; de uno en uno no encajan.
Con tornillo sin cabeza fijé el engranaje pequeño al eje del motor. Apliqué 12 V al motor para verificar que el engranaje funciona.
Terminamos la caja metiendo el panel lateral, el rodamiento para el eje de salida y la tapa superior.
Puse insertos M3 en la placa trasera para fijar todo con tornillos M3 de 20 mm. Probé la caja de nuevo: funciona genial. Vemos cómo gira el eje de salida en la parte trasera y aquí hay que insertar el imán que el AS5600 rastreará.
Fijamos la placa controladora a la caja con tornillos y tuercas M2. El AS5600 queda perfectamente alineado con el imán, así que al girar el eje medirá bien el cambio de campo magnético.
Importante: la dirección de magnetización del imán permanente es crucial. Según sea axial o diametral, debemos colocar el imán perpendicular o paralelo al chip AS5600.
Tuve que cambiar la orientación de mi imán porque no tenía la magnetización correcta para que el AS5600 lo midiera.
Luego soldé dos cables al motor DC y lo conecté a la placa con el bornier. Para la alimentación, conecté dos cables al bornier de potencia, que al otro lado tienen conector DC para fuente de 12 V. ¡Y listo, nuestro servo personalizado está hecho!
Programación del Controlador
Queda dar vida al servo, o programar el controlador. Primero hay que grabar el bootloader en el ATmega328p. Sin bootloader el micro no entenderá el código que le enviemos.
Grabación del Bootloader
Para grabar el bootloader en el ATmega328p necesitamos una placa Arduino, en mi caso una Arduino Nano.
Usaremos comunicación SPI, así que conectamos los pines SPI correspondientes en la Arduino y nuestra placa.
En el IDE Arduino, abrimos el ejemplo ArduinoISP y lo subimos a la Nano. Con este código la Nano puede grabar el bootloader en el ATmega328.
En el menú Herramientas, como Programador seleccionamos «Arduino as ISP» y pulsamos «Grabar bootloader».
Mientras graba, veremos que los LEDs de la Nano parpadean mucho, y al acabar tendremos el bootloader grabado.
Subida del Código
Hecho eso, ya podemos programar o subir el código a la placa con un módulo USB-UART.
La placa tiene pines dedicados para conectarlos fácilmente como en el esquema.
Abrimos el código de este servo personalizado y lo subimos. Antes, instalamos las librerías del AS5600 y control PID desde el Gestor de Librerías del IDE. Al pulsar Subir, el código se graba en nuestro ATmega328 vía el módulo USB-UART.
¡Listo! Nuestro servo personalizado está hecho. Conectamos un potenciómetro para probarlo. Nota: la entrada analógica va al pin «S» de la placa, no al «A». Al diseñar el PCB conecté mal esos dos pines al ATmega328.
Seleccionamos modo analógico con el DIP switch y alimentamos el servo.
Y aquí está: controlamos la posición del servo con la entrada analógica del potenciómetro. Hemos convertido nuestro motor DC en un servo motor.
Código Fuente
Veamos el código de este servo personalizado.
/*
* Servo Motor Personalizado - Código Arduino
* por Dejan, www.HowToMechatronics.com
*
* Librerías:
* Encoder AS5600: https://github.com/RobTillaart/AS5600
* Controlador PID: https://github.com/br3ttb/Arduino-PID-Library/blob/master/PID_v1.h
*/
#include "AS5600.h"
#include "Wire.h"
#include
AS5600 as5600; // usar Wire por defecto
double Pk1 = 2; // velocidad de llegada
double Ik1 = 0;
double Dk1 = 0.025;
// Variables para PID
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 = "";
int centerAngle = 2047; // 180 grados
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);
// Pull-ups internos
pinMode(centerSet, INPUT_PULLUP);
pinMode(inputSwitch, INPUT_PULLUP);
pinMode(4, INPUT_PULLUP);
myPID.SetMode(AUTOMATIC);
// Configuración PID
myPID.SetOutputLimits(-255, 255);
myPID.SetSampleTime(20);
}
void loop() {
// Leer encoder - posición actual
encoderValue = as5600.readAngle();
// Modo rotación continua
if (digitalRead(modeSwitch) == 0) {
// Introducir ángulo deseado por monitor serie
while (Serial.available() > 0) {
int inChar = Serial.read();
if (isDigit(inChar)) {
inString += (char)inChar;
}
if (inChar == '\n') {
Setpoint = inString.toInt(); // Setpoint - ángulo deseado
inString = "";
}
}
if (digitalRead(inputSwitch) == 0) {
// Potenciómetro como entrada
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); // Receptor RC
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++; }
}
// Convertir RAW a ángulo
angle = encoderValue * 0.087890625;
// Cuadrantes
if (angle >= 0 && angle <= 90) { quadrantNumber = 1; }
if (angle >= 90 && angle <= 180) { quadrantNumber = 2; }
if (angle >= 180 && angle <= 270) { quadrantNumber = 3; }
if (angle >= 270 && angle <= 360) { quadrantNumber = 4; }
if (quadrantNumber != previousQuadrantNumber) {
if (quadrantNumber == 1 && previousQuadrantNumber == 4) { numberOfTurns++; }
if (quadrantNumber == 4 && previousQuadrantNumber == 1) { numberOfTurns--; }
previousQuadrantNumber = quadrantNumber;
}
if (totalAngle >= 0) {
totalAngle = (numberOfTurns * 360) + angle;
} else {
totalAngle = (numberOfTurns * 360) + angle;
}
Input = totalAngle;
}
// Modo rotación limitada
else if (digitalRead(modeSwitch) == 1) {
rangeAdjustment = analogRead(A1);
leftLimit = 0 + 30 + rangeAdjustment;
rightLimit = 4097 - 30 - rangeAdjustment;
if (digitalRead(inputSwitch) == 0) {
// Analógico - Potenciómetro
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 - Transmisor RC
inputValue = pulseIn(ch1, HIGH, 30000);
Setpoint = map(inputValue, 1000, 2000, -255, 255);
}
// Definir ángulo central
if (digitalRead(centerSet) == LOW) {
centerAngle = encoderValue;
angleDifference = 2047 - encoderValue;
delay(1000);
}
// Ajustar valor ángulo según punto central
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;
}
Input = map(angleValue, leftLimit, rightLimit, -255, 255);
}
// Ajuste sensibilidad
Pk1 = analogRead(A2) * 0.002;
myPID.SetTunings(Pk1, Ik1, Dk1);
// Proceso PID
myPID.Compute();
// Mover derecha
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);
}
// Mover izquierda
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);
}
// Quieto
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);
}
Resumen del Código
Empezamos el bucle leyendo el encoder (posición actual del eje).
// Leer encoder - posición actual
encoderValue = as5600.readAngle();
Si estamos en modo rotación continua, aceptamos valores del Monitor Serie y los usamos como setpoint para el PID.
// Introducir ángulo deseado por monitor serie
while (Serial.available() > 0) {
int inChar = Serial.read();
if (isDigit(inChar)) {
inString += (char)inChar;
}
if (inChar == '\n') {
Setpoint = inString.toInt();
inString = "";
}
}
Si el modo de entrada es potenciómetro, leemos su entrada analógica y corregimos el setpoint según lo giremos.
if (digitalRead(inputSwitch) == 0) {
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; }
}
Hacemos la misma corrección si la entrada es el receptor RC.
Convertimos los valores RAW del encoder a ángulos, y con los if seguimos en qué cuadrante está el eje.
// Convertir RAW a ángulo
angle = encoderValue * 0.087890625;
if (angle >= 0 && angle <= 90) { quadrantNumber = 1; }
if (angle >= 90 && angle <= 180) { quadrantNumber = 2; }
if (angle >= 180 && angle <= 270) { quadrantNumber = 3; }
if (angle >= 270 && angle <= 360) { quadrantNumber = 4; }
Así rastreamos la rotación y cuándo da vueltas completas. El ángulo total es el Input del PID.
if (quadrantNumber != previousQuadrantNumber) {
if (quadrantNumber == 1 && previousQuadrantNumber == 4) { numberOfTurns++; }
if (quadrantNumber == 4 && previousQuadrantNumber == 1) { numberOfTurns--; }
previousQuadrantNumber = quadrantNumber;
}
if (totalAngle >= 0) {
totalAngle = (numberOfTurns * 360) + angle;
} else {
totalAngle = (numberOfTurns * 360) + angle;
}
Input = totalAngle;
En modo rotación limitada, primero leemos el potenciómetro para ajustar el rango y actualizamos límites izquierdo y derecho.
rangeAdjustment = analogRead(A1);
leftLimit = 0 + 30 + rangeAdjustment;
rightLimit = 4097 - 30 - rangeAdjustment;
Si la entrada es potenciómetro, usamos su valor como setpoint.
if (digitalRead(inputSwitch) == 0) {
inputValue = analogRead(A0);
if (inputValue < 15) { inputValue = 15; }
if (inputValue > 1008) { inputValue = 1008; }
Setpoint = map(inputValue, 15, 1008, -255, 255);
}
Si la entrada es receptor RC, leemos PWM y lo usamos como setpoint.
else if (digitalRead(inputSwitch) == 1) {
inputValue = pulseIn(ch1, HIGH, 30000);
Setpoint = map(inputValue, 1000, 2000, -255, 255);
}
Para definir un centro distinto, comprobamos si se pulsa el botón y capturamos esa posición como nuevo centro.
if (digitalRead(centerSet) == LOW) {
centerAngle = encoderValue;
angleDifference = 2047 - encoderValue;
delay(1000);
}
Luego ajustamos las lecturas reales del encoder desplazándolas por la diferencia entre el nuevo y el viejo centro. Usamos ese valor como Input del PID.
if (centerAngle > 2047) {
angleValue = encoderValue + angleDifference;
if (encoderValue >= 0 && encoderValue < abs(angleDifference)) {
angleValue = encoderValue + 4097 + angleDifference;
}
} else if (centerAngle == 2047) {
angleValue = encoderValue;
}
Input = map(angleValue, leftLimit, rightLimit, -255, 255);
Con la entrada analógica del otro potenciómetro ajustamos la ganancia proporcional del PID, y ejecutamos el proceso PID para obtener salida.
// Ajuste sensibilidad
Pk1 = analogRead(A2) * 0.002;
myPID.SetTunings(Pk1, Ik1, Dk1);
myPID.Compute();
Usamos esa salida para pilotar el motor con PWM, izquierda, derecha o parado, según el error entre posición deseada y real.
// Mover derecha
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);
}
Eso es todo. Ten en cuenta que el código no está del todo optimizado y hay margen de mejora.
Si intentas replicar este proyecto, prepárate para solucionar problemas. Hay muchas cosas que pueden fallar, especialmente soldando esos componentes SMD tan pequeños.
No conseguí que el servo funcionara a la primera. Inicialmente tenía conexiones erróneas en el PCB, pedí otro con correcciones, pero aún necesitó varios intentos hasta que funcionó.
Esta sección del artículo está aún en construcción, por favor vuelve a comprobarla más tarde….
Proceso de manufactura
- La Evolución de las Pistolas de Agua de Acción de Bombeo: De la Invención al Liderazgo Global
- Barras Antitranspirante/Desodorante: Ciencia, Historia y Claves de Fabricación
- Entendiendo las levas: Guía para principiantes sobre su función y aplicaciones
- Replicador IR Wi-Fi: Controla dispositivos remotamente
- SIGHT: Gafas Inteligentes para Capacitar a Personas Ciegas
- Construye un Reloj Nixie Simple con Arduino – Guía Paso a Paso
- Cómo Elegir la Muelas Abrasiva Perfecta para un Rendimiento Óptimo
- Ciclotrón: diseño, historia y aplicaciones modernas en medicina e investigación
- Dominando el Fresado de Rosca de Gran Diámetro: Métodos y Habilidades Comprobados
- La Guía Definitiva para Comprar Estanterías de Almacén: Maximice Espacio y ROI
- SunGlass-BOT: Gafas de Sol Inteligentes que se Ajustan Automáticamente a la Luz