Transforme cualquier motor de CC en un servo de 360° personalizado:guía paso a paso
En este tutorial aprenderemos cómo convertir cualquier motor de CC en un servomotor personalizado e independiente con muchas funciones. A diferencia de los servos normales que tienen un movimiento limitado de 180 o 270 grados, este tiene un rango ilimitado de 360 grados y además tenemos la capacidad de ajustar el rango de rotación al valor que necesitemos.
Creo que eso es bastante útil y, además, podemos incluso ajustar el punto central del servo. Así, podemos ajustar tanto el punto central como el rango de rotación al mismo tiempo.
Puedes ver el siguiente vídeo o leer el tutorial escrito a continuación.
Otra característica es que podemos ajustar la sensibilidad o la rapidez con la que responderá el servo a nuestra entrada. Hablando de la entrada, podemos tener tres modos de entrada diferentes.
Podemos controlar el servo con una entrada de voltaje analógica o usando un potenciómetro, podemos controlar el servo con un transmisor RC así como controlar el servo a través de un puerto serie ingresando valores de ángulo a través del monitor serie en nuestra PC o computadora portátil.
También podemos hacer eso simultáneamente, controlar el servo ingresando valores a través del monitor serial y mover manualmente el servo usando el transmisor RC. El servomotor sabrá en todo momento su posición actual y podrá verla en el monitor de serie.
Además de la lista de características de este servomotor, se encuentra el modo de rotación continua. Así es. Podemos controlar y realizar un seguimiento de la posición del servomotor incluso en este modo de rotación continua. Podemos configurar el eje del servomotor para que vaya a cualquier posición con un número infinito de vueltas.
Todo esto es posible gracias al codificador de 12 bits que emplea este servomotor, el sensor de posición giratorio magnético AS5600 y el control PID implementado para accionar el motor de CC.
Hice esta placa controladora de servomotor personalizada que incluye su propio microcontrolador y todo lo demás para convertir fácilmente cualquier motor de CC en un servomotor independiente.
Sólo tenemos que colocar la placa en el centro del eje de salida (incluyendo un imán específico en el eje), conectar un motor DC de cualquier tamaño con corriente nominal de hasta 3,5A, alimentar todo el sistema con 12V y listo, obtenemos un servomotor de un motor DC normal con todas estas características.
Ahora te guiaré a través de todo el proceso de fabricación de este servomotor personalizado para que también puedas fabricar uno por tu cuenta. Explicaré el principio de funcionamiento de un servomotor, un controlador de circuito cerrado, un controlador PID, cómo diseñé la PCB personalizada y la caja de cambios, además de explicar el código detrás de esto.
Principio de funcionamiento del servomotor
Para explicar el principio de funcionamiento de un servomotor, desarmemos un servomotor RC típico y veamos qué hay dentro.
Podemos notar que tiene un pequeño motor DC, una placa controladora, un potenciómetro y una conexión de tres cables, dos cables para la alimentación y uno para la señal de entrada. Además, existen algunos engranajes para reducir la velocidad y aumentar el par del motor de CC.
Esta es una configuración típica para la mayoría de los servomotores RC o de hobby. El potenciómetro está conectado al eje de salida del motor de CC y actúa como sensor de posición, le indica al controlador la posición actual del eje del servomotor. La placa controladora controla el motor de CC según la señal de entrada (la posición deseada) y la posición real que obtenemos como retroalimentación del potenciómetro. Esto representa un sistema de control de circuito cerrado.
La señal de entrada, o la posición deseada, se compara con la posición real del motor que obtenemos del sensor de retroalimentación de posición. La diferencia que ocurre, que se llama error, luego se procesa en el controlador que ordena al motor que se mueva hasta alcanzar la posición deseada.
Cómo hacer un servomotor personalizado
Entonces, si queremos construir nuestro propio servomotor con algunos motores de CC más grandes que los que usan estos servos RC típicos, podemos implementar el mismo sistema de control de circuito cerrado.
Solo necesitamos un sensor de posición conectado de alguna manera al eje de salida y un microcontrolador para accionar el motor de CC.
Ahora en cuanto al sensor de posición, la solución más sencilla es utilizar un potenciómetro sencillo como el que vimos en los servos RC. Sin embargo, el problema con este tipo de potenciómetros es que tienen un rango de rotación limitado de sólo 270 grados, lo que limita directamente el rango de rotación del servomotor. También existen otros tipos de potenciómetros que pueden realizar múltiples giros y proporcionar mejor alcance y resolución, pero aún así tienen una rotación limitada.
Si necesitamos que el servomotor tenga un rango de rotación ilimitado, entonces necesitamos usar un codificador. Los codificadores son dispositivos electromecánicos que pueden realizar un seguimiento de la posición angular del eje con rotación ilimitada. Existen muchos tipos de codificadores como incrementales o absolutos, o dependiendo de su tecnología de detección son ópticos, magnéticos o capacitivos. Por supuesto, cada uno de ellos tiene sus propias ventajas y desventajas.
Codificador AS5600 – Sensor de posición giratorio magnético
Elegí utilizar un codificador magnético o el sensor de posición giratorio magnético AS5600 porque es un codificador muy compacto y fácil de implementar que proporciona alta precisión o resolución. Basta con echar un vistazo a lo pequeño que es este microchip.
Tiene un sensor de efecto Hall incorporado que puede detectar cambios en la dirección del campo magnético. Así, sólo tenemos que acoplar un imán al eje de salida del motor y colocarlo cerca del microchip a una distancia de 0,5 a 3 mm.
Ahora, cuando el eje del motor y el imán giren, el sensor de efecto Hall capturará esos cambios en la dirección del campo magnético. Con la ayuda del convertidor A/D de 12 bits incorporado, el sensor AS5600 puede generar 4096 posiciones por giro o una rotación de 360 grados.
Esto significa que puede detectar cambios de posición angular tan pequeños como 0,0878 grados. Esto es bastante impresionante y, dado que es muy asequible y fácil de conseguir, es la elección correcta para un servomotor personalizado.
Muy bien, ¿qué más necesitamos? Un microcontrolador y un controlador para el motor de CC. Elegí el controlador de motor de CC DRV8871 que puede manejar hasta 3,5 amperios de corriente y el microcontrolador Atmega328.
Elegí la versión de montaje en superficie, ya que es mucho más compacta que la versión DIP, y mi objetivo era hacer una PCB personalizada lo más pequeña posible en la que pueda incluir todo para que el servo pueda funcionar como un dispositivo independiente.
Diagrama de circuito del servomotor personalizado
Aquí está el diagrama de circuito completo de este servomotor hecho a medida.
Puede obtener los componentes necesarios para este proyecto en los enlaces siguientes:
- Codificador magnético AS5600 ………………….. Amazon / AliExpress
- Controlador de motor de CC DRV8871 …………….…. Amazon / AliExpress
- Atmega328p-AU …………………………………. Amazon / AliExpress
- Oscilador de cristal de 16Mhz…………………….. Amazon / AliExpress
- Regulador de voltaje AMS1117 5V ……..…. Amazon / AliExpress
- Potenciómetro cuadrado 3386P ………………. Amazon / AliExpress
- Kit de condensadores 0805 ………………………….…. Amazon / AliExpress
- Motor de 12 V CC – ~ 50 RPM …………….……. Amazon / Aliexpress
Divulgación:Estos son enlaces de afiliados. Como asociado de Amazon, gano con compras que califican.
Entonces, tenemos el microcontrolador Atmega328 junto con su circuito mínimo recomendado, que incluye un oscilador de 16 Mhz, algunos capacitores y una resistencia.
Para alimentar el microcontrolador y los demás componentes que requieren 5 V, utilizamos el regulador de voltaje AMS1117, que reducirá la entrada de alimentación de 12 V a 5 V.
Aquí está el sensor de posición AS5600 con su circuito recomendado que incluye dos condensadores y dos resistencias pull-up para la comunicación IC2.
El controlador de motor de CC DRV8871 necesita solo una resistencia para limitar la corriente y dos condensadores de desacoplamiento. Luego tenemos dos potenciómetros conectados a las entradas analógicas del microcontrolador, uno para ajustar el rango de rotación y otro para ajustar la sensibilidad del servo. El botón se utiliza para configurar el punto central del servo y el interruptor DIP de dos vías para seleccionar los modos de funcionamiento del servo. Hay un encabezado de pin para las entradas del servo, ya sea una entrada de voltaje analógico o una entrada PWM digital de un receptor RC, junto con un pin de 5 V y de tierra. También hay un encabezado de pin para programar el microcontrolador a través del protocolo SPI y el puerto serie.
Aquí hay un resumen de este circuito y su flujo de trabajo. La entrada, o la posición angular deseada, se recibe a través de estos dos pines y puede ser un voltaje analógico proveniente de un potenciómetro o una señal digital PWM proveniente de un receptor RC. La entrada ingresa al microcontrolador donde se compara con la posición angular real detectada por el codificador o el sensor de posición AS5600. Este sensor se comunica con el microcontrolador a través del protocolo IC2.
Luego el microcontrolador hace los cálculos, calcula el error y según él envía una señal PWM al controlador DRV8871 que impulsa el motor DC hasta alcanzar la posición deseada.
Todo el circuito se alimenta con 12 V y el regulador de voltaje AS1117 proporciona 5 V para el microcontrolador y los demás componentes de forma adecuada.
Diseño de PCB
Según el diagrama del circuito, intenté diseñar la PCB lo más pequeña posible y resultó ser de 40x40 mm.
Coloco el codificador en la parte inferior y exactamente en el punto central de la PCB, para que pueda montarse y alinearse fácilmente con el eje de salida del servo.
Todos los demás componentes están ubicados en el otro lado para que no interfieran con el codificador y el eje de salida.
Pedí el PCB a PCBWay. Aquí podemos simplemente cargar el archivo Gerber, elegir las propiedades de nuestra PCB y pedirlo a un precio razonable.
Diseñé el PCB para que tuviera 4 capas, las del medio son para GND, lo que aumenta un poco el precio. No cambié ninguna de las propiedades predeterminadas, excepto el color de la PCB, que elegí blanco, y marco que acepto el cambio del acabado de la superficie a Oro de inmersión, si corresponde, sin cargo adicional.
Puede encontrar y descargar Gerber en la comunidad de intercambio de proyectos PCBWay a través de la cual también puede solicitar directamente la PCB.
Sin embargo, después de varios días llegó la PCB. La calidad de la PCB es excelente, todo es igual que en el diseño y lo obtuve con un acabado de superficie de oro por inmersión.
Muy bien, ahora podemos continuar soldando los componentes. Empecé con los componentes más pequeños, como este indicador LED, los condensadores y las resistencias.
De hecho, esta es la primera vez que soldo estos pequeños componentes SMD y lo hice muy, muy mal.
El mayor desafío fue soldar el microcontrolador Atmega328, ya que los pines son muy pequeños y están muy cerca uno del otro, pero de alguna manera logré hacerlo.
El microchip del codificador AS5600 fue fácil de soldar en la parte posterior de la PCB, así como en los componentes más grandes con orificios pasantes, como el interruptor DIP, los potenciómetros, los bloques de terminales y los cabezales de pines.
De todos modos, aquí está la apariencia final de la placa controladora que, después de todo, creo que resultó decente.
Ahora es el momento de fabricar una caja de cambios adecuada para el motor de CC y esta placa controladora.
Modelo 3D de servo personalizado
Diseñé la caja de cambios para este servomotor personalizado usando Onshape. El diseño de la caja de cambios depende, por supuesto, del motor CC. Como mencioné, podemos usar un motor de CC de cualquier tamaño en combinación con la placa controladora que acabamos de fabricar.
Aquí estoy usando un motor de CC con un diámetro de 37 mm y una caja de cambios incorporada que produce 50 RPM. 50 RPM es una buena velocidad para un servomotor, pero quería bajar un poco más para obtener un mejor par, así que hice una caja de cambios con una reducción de 3 veces. Utilicé engranajes en espiga para ese propósito, ya que son eficientes y fáciles de hacer con una impresora 3D.
Por supuesto, aquí tenemos la libertad de hacer este diseño de caja de cambios como queramos, ya que depende del motor DC que queramos usar y de las velocidades de salida que queramos obtener.
Coloqué la placa del controlador en la parte posterior de esta caja de cambios y la alineé perfectamente en el centro del eje de salida.
En caso de que queramos usar el eje del motor de CC directamente como salida, podemos usar un juego de engranajes 1:1 para poder rastrear la posición del eje correctamente. O también podríamos utilizar un sistema de cinturón en tal caso. Como dije, tenemos infinitas posibilidades para hacer la caja de cambios.
Descargar modelo 3D y archivos STL
Puede ver y explorar el modelo 3D de este servomotor personalizado directamente en su navegador web con Onshape. (Para ello necesitas una cuenta de Onshape; puedes crear una cuenta gratuita para usar en casa)
Por supuesto, también puedes descargar el modelo 3D, así como los archivos STL necesarios para imprimir las piezas en 3D desde aquí:
Archivo PASO:
Archivos STL para impresión 3D:
Montando el servo personalizado
Aquí están las piezas impresas en 3D para esta construcción para que podamos comenzar a ensamblar el servomotor.
Junto a ellos necesitamos unos tornillos M3 e insertos roscados, y unos rodamientos.
Primero, aseguré el motor de CC a la placa base con algunos pernos M3 de 8 mm de longitud.
Luego podemos instalar los dos engranajes en su lugar. El engranaje más pequeño va directamente al eje del motor de CC y el engranaje más grande será la salida del servo. Sin embargo, el eje de salida del se compone de dos partes.
Instalé inserciones roscadas en ambos lados de esta parte del eje de salida, en un lado para conectar el engranaje y en el otro lado para sujetar cosas en la salida del servo.
También instalé inserciones roscadas en el engranaje más pequeño que se usará para asegurarlo al eje del motor de CC. Ahora podemos deslizar los engranajes pelados a su posición. Al ser engranajes en espiga debemos deslizarlos ambos en su sitio a la vez, de lo contrario no podremos emparejarlos si los introducimos uno a uno.
Usando un tornillo prisionero, aseguré el engranaje pequeño al eje del motor de CC. Apliqué 12 V al motor de CC para comprobar si el juego de engranajes funcionará correctamente.
Podemos finalizar el montaje de la caja de cambios introduciendo el panel lateral, el rodamiento de bolas para el eje de salida y la tapa superior.
Instalé algunos insertos roscados M3 en la placa posterior para que podamos asegurar todo el conjunto con unos pernos M3 de 20 mm de largo. Probé la caja de cambios nuevamente, funciona muy bien. Podemos notar cómo el eje de salida gira en la parte posterior y aquí debemos insertar el imán que el codificador AS5600 realizará un seguimiento.
Fijamos la placa del controlador a la caja de cambios mediante unos tornillos y tuercas M2. El sensor de posición AS5600 ahora está perfectamente alineado con el imán y, por lo tanto, cuando el eje de salida gire, medirá el cambio en el campo magnético correctamente.
Tenga en cuenta aquí que la dirección de magnetización del imán permanente es muy importante. Dependiendo de si está magnetizado axial o diametralmente, debemos colocar el imán perpendicular o paralelo a ese IC AS5600.
Terminé cambiando la dirección de mi imán, ya que no tenía la magnetización adecuada para que el codificador AS5600 pudiera medirlo.
Luego, soldé dos cables al motor de CC y conecté el motor al controlador con el bloque de terminales. En cuanto a la alimentación, conecté dos cables al bloque de terminales de alimentación, que en el otro lado tiene un conector de alimentación CC para conectar una fuente de alimentación de 12V. Y eso es todo, nuestro servomotor personalizado está listo.
Programación del controlador
Lo que queda por hacer ahora es darle vida a este servo, o programar el controlador. Para ello, primero necesitamos grabar un gestor de arranque en el microcontrolador ATmega328p. Sin un gestor de arranque el microcontrolador no podrá entender el idioma ni el código que le enviaremos.
Grabar cargador de arranque
Para grabar el gestor de arranque en el ATmega328p, necesitamos una placa Arduino, en mi caso usaré una placa Arduino Nano.
Usaremos la comunicación SPI, por lo que necesitamos conectar los pines SPI adecuados en la placa Arduino y nuestra placa controladora.
Ahora, usando el IDE de Arduino, debemos abrir el boceto de ejemplo de ArduinoISP y cargarlo en la placa Arduino Nano. Con este código, el Arduino Nano ahora es capaz de grabar el gestor de arranque en el microcontrolador ATmega328.
A continuación, desde el menú Herramientas, como programador, debemos seleccionar Arduino como ISP y luego hacer clic en Grabar cargador de arranque.
Mientras graba el gestor de arranque, debemos notar que las luces Arduino NANO parpadearán mucho, lo que resultará en una grabación exitosa del gestor de arranque.
Carga de código
Una vez que hayamos terminado con eso, ahora podemos programar o cargar el código en la placa del controlador con la ayuda de un módulo de interfaz USB a UART.
La placa del controlador tiene pines dedicados para conectarlos fácilmente, como se muestra en este diagrama de circuito.
Ahora podemos abrir el código de este servo personalizado que hice y cargarlo en el controlador. Sin embargo, antes de hacer eso, primero debemos instalar las bibliotecas para el sensor AS5600 y el control PID. Podemos hacerlo fácilmente desde el Administrador de biblioteca IDE de Arduino. Una vez que presionemos el botón de carga, el código se escribirá en nuestro controlador ATmega328 a través del módulo de interfaz USB a UART.
Y eso es todo, nuestro servomotor personalizado está listo. Ahora podemos conectarle un potenciómetro para probarlo. Solo tenga en cuenta que la entrada analógica va al pin "S" de la placa del controlador, en lugar del pin "A".
Al diseñar la PCB, conecté estos dos pines incorrectamente al ATmega328. Luego podemos seleccionar el modo de entrada analógica a través del interruptor DIP y alimentar el servo.
Y aquí está, podemos controlar la posición del servomotor con la ayuda de la entrada analógica del potenciómetro. Hemos convertido con éxito nuestro motor CC en un servomotor.
Código fuente
Ahora echemos un vistazo al código de este servomotor personalizado.
/*
* 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) Descripción general del código
Entonces, comenzamos el ciclo leyendo el valor del codificador o la posición actual del eje.
// Read encoder value - current position
encoderValue = as5600.readAngle();Code language: JavaScript (javascript) Luego si estamos en modo de rotación Continua, aceptamos valores del monitor serie y los usamos como punto de ajuste o ángulo deseado para el controlador PID.
// 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) Si el modo de entrada está configurado en potenciómetro, leemos su entrada analógica y corregimos el valor del setpoint dependiendo de cuánto lo giramos.
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) Hacemos la misma corrección del setpoint si la entrada es el receptor RC.
Aquí convertimos los valores del codificador RAW en valores de ángulo, y con estas declaraciones if realizamos un seguimiento en qué cuadrante está la posición actual del eje.
// 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) Con esta información, podemos realizar un seguimiento de cómo gira el eje y cuándo dará una vuelta completa. El ángulo total es el valor de entrada para el controlador PID.
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) Por otro lado, si estamos en modo de rotación limitada, primero leemos el valor del potenciómetro que se usa para ajustar el rango de rotación y ajustamos el límite de rotación izquierdo y derecho en consecuencia.
rangeAdjustment = analogRead(A1);
leftLimit = 0 + 30 + rangeAdjustment;
rightLimit = 4097 - 30 - rangeAdjustment; Si el modo de entrada es el potenciómetro, utilizamos su valor como valor de consigna para el controlador PID.
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) Si el modo de entrada es el receptor RC, leemos el valor PWM entrante del receptor y usamos ese valor como punto de ajuste.
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) Para establecer un punto central diferente, verificamos si hemos presionado el botón y capturamos esa posición como un nuevo punto central.
// Set center angle
if (digitalRead(centerSet) == LOW) {
centerAngle = encoderValue;
angleDifference = 2047 - encoderValue;
delay(1000);
}Code language: JavaScript (javascript) Según esto, entonces tenemos que ajustar las lecturas reales del codificador y compensarlas por la diferencia de ángulo entre el punto central nuevo y el antiguo. Usamos ese valor como valor de entrada para el controlador PID.
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) Usando la entrada analógica del otro potenciómetro ajustamos la ganancia proporcional del controlador PID y finalmente ejecutamos el proceso PID para obtener un valor de salida.
// 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) Usamos ese valor de salida para accionar los motores de CC con señal PWM, izquierda o derecha, o en posición fija dependiendo del valor de salida del controlador PID, o dependiendo del error entre la posición deseada y la posición real que lee el codificador.
// 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) Eso sería todo por este video. Tenga en cuenta que el código no está bien optimizado y se puede mejorar.
Además, si intenta recrear este proyecto, debe estar preparado para solucionar el problema. Hay muchas cosas que podrían salir mal, especialmente al soldar esos pequeños componentes SMD.
No logré que este servo funcionara desde el primer intento. Inicialmente, tenía algunas conexiones incorrectas en la PCB, luego pedí la PCB nuevamente con nuevas actualizaciones, pero aún necesitaba algunos intentos más hasta que lograra que funcionara.
Esta sección del artículo aún está en construcción, compruébela un poco más tarde….
Proceso de manufactura
- Introducción a la soldadura de tuercas por proyección
- Explorando los 3 procesos de fabricación de metal
- Construya un tanque RC impreso en 3D de alto rendimiento con caja de cambios de doble velocidad
- ¿Qué son los martillos de potencia? - Tipos, diseño y funcionamiento
- Estación meteorológica basada en Raspberry Pi
- Enviar en una botella
- ¿Qué son los reductores de engranajes rectos?
- Explicación de la colada continua:tipos, beneficios y proceso de producción
- Brazo robótico Arduino impreso en 3D
- Saber cuándo y cómo elegir una bomba de refuerzo automática para su hogar
- Posture Pal con Walabot