Manufactura industrial
Internet industrial de las cosas | Materiales industriales | Mantenimiento y reparación de equipos | Programación industrial |
home  MfgRobots >> Manufactura industrial >  >> Manufacturing Technology >> Proceso de manufactura

Construya un servoactuador lineal de precisión con retroalimentación de posición:guía paso a paso

En este tutorial aprenderemos cómo hacer un servoactuador lineal. A diferencia de los actuadores lineales normales que se mueven en una dirección particular cuando se aplica un voltaje, este servoactuador lineal personalizado proporciona movimientos precisos y repetibles que se pueden controlar fácilmente.

Se llama servoactuador porque cuenta con un sistema de circuito de retroalimentación a través del cual podemos controlar con precisión el movimiento de salida del actuador.

Puedes ver el siguiente vídeo o leer el tutorial escrito a continuación.

Descripción general

La entrada para controlar este servoactuador lineal puede ser analógica o digital. En el caso de una entrada analógica, puede ser cualquier tipo de potenciómetro como se muestra aquí. Un potenciómetro lineal, un potenciómetro giratorio común o, por ejemplo, un joystick que también es un potenciómetro giratorio, etc.

En el caso de entrada digital, podremos controlar el actuador con un Transmisor RC. Por supuesto, para esta configuración también necesitamos un receptor RC que actúa como entrada al actuador.

Para estos modos de entrada analógica y digital, solo necesitamos 3 cables para realizar una conexión, 2 de los cuales son para alimentar el dispositivo de entrada y el tercero es para la señal de entrada.

Una característica interesante que tiene este servoactuador lineal personalizado es que podemos establecer una posición inicial y final personalizada para la varilla de salida, así como ajustar la sensibilidad o la rapidez con la que el actuador responderá a nuestra entrada. 

Sin embargo, mi característica favorita es la capacidad de controlar este actuador desde una PC o computadora portátil a través de un puerto serie de comunicación. Podemos introducir valores en milímetros a través del monitor Arduino IDE Serial y el actuador se moverá a esa posición.

Lo que es aún más genial, podemos hacer movimientos repetibles o almacenar las posiciones escribiendo "guardar" en el monitor en serie en cada posición que queramos, y luego decirle al actuador que repita los movimientos en un bucle, escribiendo "ejecutar" en el monitor en serie.

Ahora déjame explicarte todo lo que necesitas saber sobre este servoactuador lineal hecho a medida, cómo funciona y cómo lo diseñé, para que tú también puedas construir uno por tu cuenta. 

Cómo funciona

Por lo tanto, el sistema de control de circuito cerrado se basa en el sensor de posición giratorio magnético AS5600 y el control PID implementado para accionar el motor de CC.

En realidad, estoy usando la misma placa controladora de servomotor personalizada que hice en mi video anterior, que incluye su propio microcontrolador y todo lo demás para convertir fácilmente cualquier motor de CC en un servomotor independiente.

Puede consultar ese tutorial para obtener una explicación detallada de cómo funcionan un servomotor y un sistema de control de circuito cerrado.  

Muy rápido, un servomotor es un sistema de control de circuito cerrado donde 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. 

Por lo tanto, este servoactuador lineal tiene el mismo principio de funcionamiento que un servomotor, pero con un paso adicional para convertir el movimiento de rotación del motor en un movimiento lineal con la ayuda de un mecanismo de tornillo de avance.

Diseño de servoactuador lineal

Aquí tenéis el modelo 3D de este servoactuador lineal, desde donde podemos ver cómo funciona todo.

El sensor de posición giratorio magnético AS5600 está ubicado en la parte posterior del actuador y realiza un seguimiento de la rotación del tornillo principal. El tornillo de avance que uso tiene un paso de 8 mm, lo que significa que, con cada rotación completa, la tuerca del tornillo de avance realiza un movimiento lineal de 8 mm.

El AS5600 es un codificador de 12 bits, lo que significa que puede generar 4096 posiciones por vuelta. Si dividimos 8 entre 4096, obtenemos una resolución de 0,001953 mm. Ese es el cambio de posición más pequeño que el codificador AS5600 puede detectar. Creo que es bastante impresionante. 

El motor de CC que utilizo es un motor de 12 V con caja reductora incluida que produce 480 RPM. Si dividimos el 480 entre 60, obtenemos un valor de 8 revoluciones por segundo, y si multiplicamos ese número por 8, como el tornillo de avance tiene un paso de 8 mm, obtenemos una velocidad lineal del actuador de 64 mm/s.

Descubrí que estaba en el lugar, porque el recorrido máximo de esta varilla del actuador es de 150 mm, por lo que tomaría alrededor de 2,5 s desde la posición inicial a la final a velocidad máxima, o alrededor de 3 s si incluimos la aceleración y desaceleración. Por lo tanto, utilicé una relación de engranajes de 1:1 para accionar el tornillo de avance. 

El diseño de todo el actuador lineal se basa en el tamaño de la PCB controladora del servomotor hecha a medida y, por supuesto, del tornillo de avance y la tuerca del tornillo de avance. La PCB tenía unas dimensiones de 40x40mm, por lo que ese era el tamaño mínimo del bloque de cilindros.

La tuerca del husillo de 8 mm tenía una dimensión exterior de 22 mm, por lo que diseñé la varilla de acuerdo con ella. La tuerca y la varilla están conectadas con cuatro pernos M3 e insertos roscados. En la parte superior de la varilla, hay un cojinete que se desliza sobre el bloque de cilindros y se utiliza para guiar la varilla y evitar que gire. 

En la tapa del cilindro de salida tenemos 4 pequeños cojinetes que guían la varilla fuera del bloque de cilindros.

En general, creo que el actuador lineal resultó lo suficientemente compacto teniendo en cuenta todos los componentes utilizados.

También logré colocar un microinterruptor de límite dentro del bloque de cilindros, que se usa para localizar y configurar la posición inicial del actuador.

Descarga de modelo 3D

Puede ver y explorar el modelo 3D de este servoactuador lineal personalizado directamente en su navegador web con Onshape. (necesitas una cuenta de Onshape para eso; puedes crear una cuenta gratuita para usar en casa)

Puede obtener los archivos STL necesarios para la impresión 3D, así como el archivo STEP de este modelo 3D en Cults3D.

Algo más que mencionar aquí es que puede aumentar fácilmente la longitud máxima de recorrido de este actuador lineal, simplemente aumentando la longitud del bloque de cilindros y la varilla. Elegí estas dimensiones porque quería que todas las piezas encajaran en una impresora 3D con una base de impresión más pequeña de 220x220 mm. La parte más grande aquí es la varilla, que mide 215 mm de largo.

Impresión 3D

Mi nueva Creality Ender-3 V3 SE hizo un gran trabajo imprimiéndola en orientación horizontal a lo largo del eje Y. Aunque necesitamos enviar un poco, imprimir la varilla en esta orientación contribuirá a un funcionamiento más suave y a una varilla más resistente.

Al imprimir en 3D, es importante utilizar la función de expansión horizontal en su software de corte para compensar la expansión del filamento y obtener piezas dimensionalmente más precisas.

Utilicé un valor de –0,1 mm, pero deberías hacer algunas impresiones de prueba para ver qué valor se adapta a tu impresora 3D. 

Imprimí el bloque de cilindros a lo largo del eje Z para evitar imprimir mucho material de soporte. La Creality Ender-3 V3 SE también hizo un gran trabajo para esta impresión.

Me sorprendió gratamente la calidad de impresión que ofrece esta impresora 3D teniendo en cuenta su precio. Es muy fácil configurar la impresora 3D, tiene nivelación automática de la base, extrusora directa, excelente calidad de impresión y mayores velocidades de impresión de hasta 250 mm/s. Todo esto por poco menos de $200 la convierte en una de las mejores impresoras 3D para quienes tienen un presupuesto limitado.

Echa un vistazo a esta impresora 3D en la tienda Creality o Amazon . Consulte también mi reseña detallada en mi sitio web.

Montaje

De todos modos, aquí están todas las piezas impresas en 3D, por lo que ahora podemos comenzar a ensamblar el actuador lineal.

Lista de piezas

Puede obtener los componentes necesarios para este proyecto de servoactuador lineal en los enlaces siguientes:

Mecánico:

Electrónica:

Divulgación:Estos son enlaces de afiliados. Como asociado de Amazon, gano con compras que califican.

Montaje del mecanismo del husillo

Primero, necesitamos instalar el tornillo de avance en su lugar en el bloque de la base del cilindro. Para ello, primero debemos insertar esta tuerca impresa en 3D que tiene la misma rosca que el tornillo de avance.

Es un poco difícil atornillar la tuerca al tornillo principal porque encaja perfectamente, pero eso es lo que necesitamos aquí. Esta tuerca retiene toda la fuerza cuando la varilla empuja, por lo que cuanto más apretado esté el ajuste, más fuerza podrá retener. Además de eso, la tuerca también tiene un orificio para insertar un inserto roscado para asegurarla al eje con un tornillo prisionero.

El tornillo de avance se mantiene en su lugar en el bloque de base del cilindro con la ayuda de dos rodamientos de bolas con un diámetro exterior de 22 mm.

En la parte trasera va el engranaje que acciona el tornillo de avance. Este engranaje también tiene una rosca a juego y dos orificios para insertos roscados para asegurarlo al tornillo de avance con tornillos prisioneros.

Esta conexión también es crítica ya que transfiere todo el par del motor al tornillo de avance, por lo que no debe deslizarse. 

Para realizar este subconjunto, primero necesitamos instalar los insertos roscados en el engranaje y la tuerca, así como algunos en el bloque de cilindros.

Enroscamos el engranaje y la tuerca en sentido contrario pero no demasiado apretados ya que esto añade fuerzas axiales a los rodamientos. Luego, utilizando unos tornillos prisioneros, podemos fijar la tuerca y el engranaje al tornillo de avance.

Una vez asegurado, podemos notar que el tornillo de avance aún no está fijado en su lugar. Necesitamos agregar esta placa al bloque de cilindros para garantizar que los cojinetes permanezcan en su lugar en el bloque de cilindros.

Esto completa este subconjunto; El tornillo de avance ahora se encuentra firmemente en su lugar mientras puede girar libremente. 

A continuación, podemos preparar la varilla. La varilla es hueca en toda su longitud para alojar el tornillo de avance. Para conectar la tuerca del husillo y la varilla, primero necesitamos instalar algunos insertos roscados. 

En la parte superior de la varilla, debemos instalar el rodamiento guía con un diámetro exterior de 13 mm y un diámetro interior de 6 mm.

Colocamos el rodamiento sobre un eje hueco de 6mm impreso en 3D y lo fijamos a la varilla con un tornillo avellanado M3 de 10mm de longitud. La varilla ya está lista y podemos ver cómo se deslizará en los carriles guía del cilindro.

A continuación, debemos fijar el cilindro al bloque de base del cilindro. Sin embargo, antes de hacer eso, debemos instalar el microinterruptor de límite en su lugar.

Primero, debemos soldarle los cables, en la conexión NC. Los cables deben tener unos 15 cm de largo. Los cables se pasan a través de un orificio en la parte superior del cilindro, y luego podemos asegurar el micro final de carrera al cilindro con la ayuda de dos pernos M2 de 8 mm de longitud.

Necesitarás específicamente este microfinal de carrera para que el rodamiento guía lo dispare justo en el momento adecuado, sin golpear nada más.

Si no encuentras el modelo de final de carrera exacto, por supuesto, puedes modificar los agujeros y el mecanismo. 

Para fijar el cilindro al bloque base necesitamos instalar aquí algunos insertos roscados. Luego podemos asegurarlo en su lugar usando dos pernos M4 de 25 mm de longitud. En este momento debemos insertar sólo los dos pernos superiores.

Los dos inferiores irán un poco más tarde al instalar la caja de cambios y la cubierta de la PCB porque se utilizan los mismos orificios para asegurar la cubierta. 

A continuación, podemos atornillar la varilla en el tornillo de avance. El cojinete guía debe ir entre los rieles guía del cilindro.

Al girar el engranaje en la parte posterior, la varilla se moverá hacia atrás, hasta llegar al micro interruptor de límite. 

Luego, podemos colocar la tapa del cilindro en su lugar. La tapa del cilindro acomodará cuatro rodamientos pequeños con un diámetro exterior de 9 mm. Los ejes de estos rodamientos se pueden imprimir en 3D.

Debemos tener cuidado a la hora de introducirlos en su sitio, ya que la parte donde van estos ejes es bastante pequeña y podría romperse con facilidad. Me pasó varias veces, así que asegúrese de que se ajusten fácilmente. Estos cojinetes soportarán y guiarán la varilla para un funcionamiento más suave.

La tapa del cilindro se fija en su lugar con cuatro pernos M4.

Instalación del motor CC

Bien, a continuación podemos insertar el motor de CC en su lugar. Aseguramos el motor DC con seis tornillos M3. Luego podemos instalar el engranaje en el eje del motor.

Para fijar el engranaje en su lugar utilizamos dos insertos roscados y tornillos prisioneros. 

Una vez que los engranajes estén emparejados correctamente, podemos continuar colocando los engranajes y la cubierta de la PCB en la parte posterior del actuador lineal. Para ello, primero necesitamos instalar algunos insertos roscados más en el bloque de la base del cilindro.

Luego podemos conectar los cables al motor DC. En mi caso los soldé directamente al motor DC.

La longitud de los cables debe ser de unos 20 cm. En el bloque de base de cilindros existe un orificio por donde debemos pasar los cables tanto del motor DC como del final de carrera.

Luego también debemos pasarlos por dos soportes que hay en la tapa, lo que asegurará que queden alejados del equipo. 

En este punto, ya podemos fijar la tapa al bloque base. Para ello, primero debemos insertar los dos pernos M4 en la parte inferior, pero no completamente.

Debemos dejar unos 2mm o 3mm, para poder colocar el soporte de la tapa entremedio y luego fijar esos tornillos junto con la tapa.

Toda esta operación es un poco complicada, pero tenía que ser así porque quería que la cubierta fuera lo más pequeña posible y de una sola impresión, y los soportes de PCB estaban bloqueando el paso de los pernos.

Instalación de la PCB del servocontrolador personalizado

De todos modos, una vez que hayamos terminado con la cubierta, podemos instalar la placa controladora del servomotor personalizada en su lugar. Como dije, es el mismo controlador de mi video anterior donde les mostré cómo se puede convertir cualquier motor de CC en un servomotor.

El componente principal aquí es el codificador de posición giratorio magnético AS5600, que realiza un seguimiento de la posición angular del imán conectado al eje de salida. En este caso, fijaremos el imán al engranaje de salida del tornillo principal. El imán se alinea perfectamente con el sensor AS5600 cuando la PCB se coloca en su lugar.

Para asegurar la PCB, primero debemos insertar tuercas M2 en las ranuras de los soportes y luego apretar la PCB con cuatro pernos M2.

Lo que queda por hacer ahora es conectar los cables en su lugar. Los cables del motor de CC van al bloque de terminales del motor y se debe verificar adicionalmente la polaridad para que coincida con el programa del controlador.

En realidad, antes de conectar el motor a la PCB, podemos aplicarle algo de voltaje para comprobar si el mecanismo del tornillo de avance funciona correctamente.

En cuanto a los cables del interruptor de límite, como no tengo pines dedicados para este propósito, soldé el cable de tierra a la almohadilla de tierra del capacitor electrolítico y el cable de conexión NC al pin SCK, que es el pin digital número 13 en el microcontrolador ATMEGA328.

El bloque de terminales de alimentación está justo al lado de la cubierta, por lo que hay un orificio a través del cual conecté un conector de alimentación de 5,5 mm.

También agregué un disipador de calor al controlador del motor de CC. Finalmente, podemos poner la tapa a presión en la parte trasera y listo, hemos terminado con este proyecto. 

Ahora podemos conectar cualquier tipo de potenciómetro o receptor RC a los pines de entrada apropiados, y podemos controlar con él la posición del actuador lineal.

Como ya mencioné, en mi video anterior expliqué en detalle cómo funciona este controlador, su esquema de circuito y cómo hice el PCB.

Por lo tanto, deberías consultar ese tutorial si quieres crear esta placa controladora. 

Esquema del circuito

Muy rápido, el componente principal es el sensor magnético AS5600, que realiza un seguimiento de la posición de la salida del actuador. Los datos del sensor van al cerebro de esta placa de servocontrolador, el microcontrolador Atmega328, que hace los cálculos y le indica al controlador del motor de CC DRV8871 cómo accionar el motor de CC.

El controlador de motor de CC DRV8871 puede manejar hasta 3,6 A de corriente máxima. Para alimentar la placa, podemos usar 12 V que luego se reduce a 5 V con un regulador de voltaje ASM1117 para el Atmega328 y los otros componentes de 5 V. Disponemos de un interruptor DIP de dos canales a través del cual seleccionamos el modo de entrada del actuador, ya sea analógico o digital, o mediante comunicación por puerto serie.

Uno de los potenciómetros de ajuste se usa para ajustar la sensibilidad del actuador y el botón SDM se usa para configurar las posiciones inicial y final.

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.

De todos modos, también puedes realizar este proyecto de actuador lineal incluso sin este servocontrolador personalizado, por supuesto.

Puede utilizar el sensor AS5600 en una placa de conexión en combinación con una placa Arduino para controlar el motor de CC.

Código

Ahora echemos un vistazo al código de este servoactuador lineal:

/*
 Linear Servo Actuator - 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 = 0.65; //speed it gets there
double Ik1 = 0;
double Dk1 = 0.1;
//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 setButton 7
#define inputSwitch 3
#define modeSwitch 4
#define limitSwitch 13
int ch1Value;
long encoderValue, desiredValue, pwmValue;
String serialInput = ""; // string to hold input
int serialIntInput;
double totalDistance = 0;
long startPosition = 358;
long endPosition = 6750;
long rangeAdjustment = 0;
float sensitivityAdjustment = 0;
float angle = 0;
float angleValue = 0;
float rodPosition;
float positionsArray[100];
int positionsCounter = 0;
long quadrantNumber = 2;
long previousQuadrantNumber = 3;
long numberOfTurns = 0;
float totalAngle = 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(setButton, INPUT_PULLUP);
 pinMode(inputSwitch, INPUT_PULLUP);
 pinMode(modeSwitch, INPUT_PULLUP);
 pinMode(limitSwitch, INPUT_PULLUP);
 // PID Setup
 myPID.SetMode(AUTOMATIC);
 myPID.SetOutputLimits(-255, 255);
 myPID.SetSampleTime(20);
 // --- HOMING ----
 // Move backward until you ...
 while (digitalRead(limitSwitch) != 1) {
 digitalWrite(motor_IN1, LOW);
 analogWrite(motor_IN2, 70);
 encoderValue = as5600.readAngle();
 }
 while (digitalRead(limitSwitch) != 0) {
 analogWrite(motor_IN1, 50);
 digitalWrite(motor_IN2, LOW);
 }
 digitalWrite(motor_IN1, LOW);
 digitalWrite(motor_IN2, LOW);
 startPosition = as5600.readAngle() * 0.087890625;
 endPosition = 6000;
 Setpoint = startPosition;
 // --- HOMING End ---
}
void loop() {
 // Read encoder value - current position
 rodPosition = as5600.readAngle() / 0.001953125; // in millimters - The lead screw is 8mm per rotation, and the encoder RAW value is 4096 per roration, so 8/4096 to get the value in milimiters
 // Serial communication mode - Read data from the serial monitor
 if (digitalRead(modeSwitch) == 0) {
 while (Serial.available() > 0) {
 serialInput = Serial.readString();
 serialInput.trim();
 // If "save" string is sent through the serial monitor, save the current rodPosition into the array
 if (serialInput == "save") {
 positionsArray[positionsCounter] = totalDistance;
 delay(1000);
 positionsCounter++;
 }
 // Clear the saved positions
 if (serialInput == "clear") {
 // Clear the array data to 0
 memset(positionsArray, 0, sizeof(positionsArray));
 positionsCounter = 0;
 }
 // Convert the String to Integer and use it as a Setpoint for the PID control
 serialIntInput = serialInput.toInt();
 if (serialIntInput != 0) {
 if (serialIntInput < 0) {
 serialIntInput = 0;
 }
 if (serialIntInput > 150) {
 serialIntInput = 150;
 }
 Setpoint = serialIntInput * 45; // convert mm into degrees (1mm linear movement equals 45 degrees rotational movement)
 }
 }
 
 // Run stored positions
 if (serialInput == "run") {
 while (serialInput != "stop") {
 for (int i = 0; i <= positionsCounter - 1; i++) {
 if (serialInput == "stop") {
 break;
 }
 while (positionsArray[i] > totalDistance + 25 || positionsArray[i] < totalDistance - 25 || pwmValue != 0) {
 // Desired position / setpoint for the PID contorller
 Setpoint = positionsArray[i];
 // Read encoder - use that value as an Input for the PID control
 readEncoder();
 // Run motor - PID controller inside
 runMotor();
 
 }
 delay(2000); // Delay between steps 
 // Check the serial monitor for a stop command
 while (Serial.available() > 0) {
 serialInput = Serial.readString();
 serialInput.trim();
 }
 }
 }
 }
 }
 // Potentiometer and RC Receiver control mode
 else if (digitalRead(modeSwitch) == 1) {
 if (digitalRead(inputSwitch) == 0) { // Analog input - Potentiometer
 // Get value from potentiometer
 desiredValue = analogRead(A0);
 if (desiredValue < 15) {
 desiredValue = 15;
 }
 if (desiredValue > 1008) {
 desiredValue = 1008;
 }
 Setpoint = map(desiredValue, 15, 1008, startPosition, endPosition);
 
 } else if (digitalRead(inputSwitch) == 1) { // Digital input - RC transmitter
 desiredValue = pulseIn(ch1, HIGH, 30000); // Read RC receiver as input
 if (desiredValue < 1000 || desiredValue > 2000) {
 desiredValue = 1000;
 }
 Setpoint = map(desiredValue, 1000, 2000, startPosition, endPosition);
 }
 }
 
 // Confine the minimum and maximum values of the setpoint
 if (Setpoint > endPosition) {
 Setpoint = endPosition;
 }
 if (Setpoint < startPosition) {
 Setpoint = startPosition;
 }
 // Adjusting sensitivity
 //Pk1 = analogRead(A2) * 0.002; // Adjust the PID gain term 
 //myPID.SetTunings(Pk1, Ik1, Dk1);
 // Read encoder - use that value as an input for the PID control
 readEncoder();
 // Run motor
 runMotor();
 // Set start and end positions by pressing the "set" button
 if (digitalRead(setButton) == LOW) {
 delay(3000);
 if (digitalRead(setButton) == LOW) {
 endPosition = totalDistance;
 while (digitalRead(setButton) != HIGH)
 ;
 } else {
 startPosition = totalDistance;
 }
 }
}
void readEncoder() {
 // Convert encoder RAW values into angle values for keeping track of the angular position of the shaft
 encoderValue = as5600.readAngle() * 0.087890625;
 // Quadrant 1
 if (encoderValue >= 0 && encoderValue <= 90) {
 quadrantNumber = 1;
 }
 // Quadrant 2
 if (encoderValue >= 90 && encoderValue <= 180) {
 quadrantNumber = 2;
 }
 // Quadrant 3
 if (encoderValue >= 180 && encoderValue <= 270) {
 quadrantNumber = 3;
 }
 // Quadrant 4
 if (encoderValue >= 270 && encoderValue <= 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 (totalDistance >= 0) {
 totalDistance = (numberOfTurns * 360) + encoderValue;
 } else {
 totalDistance = (numberOfTurns * 360) + encoderValue;
 }
 // Establish Input value for PID
 Input = totalDistance; // current value of the position
}
void runMotor() {
 // Run PID process to get Output value
 myPID.Compute();
 // Move right
 if (Output > 1) {
 pwmValue = Output;
 if (pwmValue < 50 && pwmValue > 15) {
 pwmValue = pwmValue + 40;
 }
 if (pwmValue <= 15) {
 pwmValue = 0;
 }
 analogWrite(motor_IN1, pwmValue);
 digitalWrite(motor_IN2, LOW);
 }
 // Move left
 else if (Output < 1) {
 pwmValue = abs(Output);
 if (pwmValue < 50 && pwmValue > 15) {
 pwmValue = pwmValue + 40;
 }
 if (pwmValue <= 15) {
 pwmValue = 0;
 }
 digitalWrite(motor_IN1, LOW);
 analogWrite(motor_IN2, pwmValue);
 }
 // Do not move
 else if (Output > -1 && Output < 1) {
 pwmValue = 0;
 digitalWrite(motor_IN1, LOW);
 digitalWrite(motor_IN2, LOW);
 }
}
Code language: PHP (php)

Descripción del código

Entonces, comenzamos el ciclo leyendo el valor del codificador o la posición actual del actuador y lo convertimos a milímetros.

// Read encoder value - current position
 rodPosition = as5600.readAngle() / 0.001953125; // in millimters - The lead screw is 8mm per rotation, and the encoder RAW value is 4096 per roration, so 8/4096 to get the value in milimiters
Code language: PHP (php)

Luego si estamos en el “Modo de comunicación Serie” leemos los datos entrantes que ingresamos en el monitor Serie. Si la entrada es "guardar", almacenamos la posición actual del actuador, o si es "borrar", borramos todas las posiciones ya almacenadas.

// Serial communication mode - Read data from the serial monitor
 if (digitalRead(modeSwitch) == 0) {
 while (Serial.available() > 0) {
 serialInput = Serial.readString();
 serialInput.trim();
 // If "save" string is sent through the serial monitor, save the current rodPosition into the array
 if (serialInput == "save") {
 positionsArray[positionsCounter] = totalDistance;
 delay(1000);
 positionsCounter++;
 }
 // Clear the saved positions
 if (serialInput == "clear") {
 // Clear the array data to 0
 memset(positionsArray, 0, sizeof(positionsArray));
 positionsCounter = 0;
 }Code language: JavaScript (javascript)

Si la entrada es un número entero o un número, de 0 a 150, usamos ese valor como punto de ajuste.

// Convert the String to Integer and use it as a Setpoint for the PID control
 serialIntInput = serialInput.toInt();
 if (serialIntInput != 0) {
 if (serialIntInput < 0) {
 serialIntInput = 0;
 }
 if (serialIntInput > 150) {
 serialIntInput = 150;
 }
 Setpoint = serialIntInput * 45; // convert mm into degrees (1mm linear movement equals 45 degrees rotational movement)
 }
 }Code language: JavaScript (javascript)

Ingresamos los valores en milímetros, pero para realizar un seguimiento del eje giratorio, usamos grados, por lo que convertimos los valores de milímetros en grados multiplicando por 45. Esto es así porque para un movimiento lineal de 1 mm, el tornillo principal debe girar 45 grados. En caso de que tenga un paso diferente en su tornillo de avance, este número debería ser diferente. 

Si escribimos “ejecutar”, con la ayuda de algunos bucles while y for, el programa ejecutará las posiciones almacenadas repetidamente.

// Run stored positions
 if (serialInput == "run") {
 while (serialInput != "stop") {
 for (int i = 0; i <= positionsCounter - 1; i++) {
 if (serialInput == "stop") {
 break;
 }
 while (positionsArray[i] > totalDistance + 25 || positionsArray[i] < totalDistance - 25 || pwmValue != 0) {
 // Desired position / setpoint for the PID contorller
 Setpoint = positionsArray[i];
 // Read encoder - use that value as an Input for the PID control
 readEncoder();
 // Run motor - PID controller inside
 runMotor();
 
 }
 delay(2000); // Delay between steps 
 // Check the serial monitor for a stop command
 while (Serial.available() > 0) {
 serialInput = Serial.readString();
 serialInput.trim();
 }
 }
 }
 }Code language: JavaScript (javascript)

En cambio, si estamos en el modo de control de Potenciómetro y receptor RC, comprobamos si tenemos entrada analógica o digital.

// Potentiometer and RC Receiver control mode
 else if (digitalRead(modeSwitch) == 1) {
 if (digitalRead(inputSwitch) == 0) { // Analog input - Potentiometer
 // Get value from potentiometer
 desiredValue = analogRead(A0);
 if (desiredValue < 15) {
 desiredValue = 15;
 }
 if (desiredValue > 1008) {
 desiredValue = 1008;
 }
 Setpoint = map(desiredValue, 15, 1008, startPosition, endPosition);
 
 } else if (digitalRead(inputSwitch) == 1) { // Digital input - RC transmitter
 desiredValue = pulseIn(ch1, HIGH, 30000); // Read RC receiver as input
 if (desiredValue < 1000 || desiredValue > 2000) {
 desiredValue = 1000;
 }
 Setpoint = map(desiredValue, 1000, 2000, startPosition, endPosition);
 }
 }Code language: JavaScript (javascript)

Si es analógico, leemos la entrada analógica del potenciómetro y usamos ese valor como punto de ajuste o posición deseada a la que debe ir el actuador. De manera similar, si la entrada es digital, leemos los datos entrantes del receptor RC y usamos ese valor como punto de ajuste. 

Luego llamamos a las funciones personalizadas readEncoder() y runMotor() para leer la posición actual del actuador y ejecutar el control PID. Con la función readEncoder() leemos el valor actual del sensor en valores de ángulo, y con estas sentencias if realizamos un seguimiento en qué cuadrante se encuentra la posición actual del eje.

void readEncoder() {
 // Convert encoder RAW values into angle values for keeping track of the angular position of the shaft
 encoderValue = as5600.readAngle() * 0.087890625;
 // Quadrant 1
 if (encoderValue >= 0 && encoderValue <= 90) {
 quadrantNumber = 1;
 }
 // Quadrant 2
 if (encoderValue >= 90 && encoderValue <= 180) {
 quadrantNumber = 2;
 }
 // Quadrant 3
 if (encoderValue >= 180 && encoderValue <= 270) {
 quadrantNumber = 3;
 }
 // Quadrant 4
 if (encoderValue >= 270 && encoderValue <= 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 (totalDistance >= 0) {
 totalDistance = (numberOfTurns * 360) + encoderValue;
 } else {
 totalDistance = (numberOfTurns * 360) + encoderValue;
 }
 // Establish Input value for PID
 Input = totalDistance; // current value of the position
}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. 

Usando la entrada analógica del potenciómetro de ajuste podemos ajustar 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; // Adjust the PID gain term 
 //myPID.SetTunings(Pk1, Ik1, Dk1);Code language: JSON / JSON with Comments (json)
void runMotor() {
 // Run PID process to get Output value
 myPID.Compute();
 // Move right
 if (Output > 1) {
 pwmValue = Output;
 if (pwmValue < 50 && pwmValue > 15) {
 pwmValue = pwmValue + 40;
 }
 if (pwmValue <= 15) {
 pwmValue = 0;
 }
 analogWrite(motor_IN1, pwmValue);
 digitalWrite(motor_IN2, LOW);
 }
 // Move left
 else if (Output < 1) {
 pwmValue = abs(Output);
 if (pwmValue < 50 && pwmValue > 15) {
 pwmValue = pwmValue + 40;
 }
 if (pwmValue <= 15) {
 pwmValue = 0;
 }
 digitalWrite(motor_IN1, LOW);
 analogWrite(motor_IN2, pwmValue);
 }
 // Do not move
 else if (Output > -1 && Output < 1) {
 pwmValue = 0;
 digitalWrite(motor_IN1, LOW);
 digitalWrite(motor_IN2, LOW);
 }
}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.

Los tres términos del controlador PID, proporcional, integral y derivativo, están definidos en la parte superior, y ajustándolos podemos obtener varias respuestas de salida.

double Pk1 = 0.65; //speed it gets there
double Ik1 = 0;
double Dk1 = 0.1;Code language: JavaScript (javascript)

La calidad, qué tan bien funcionará el actuador o responderá a nuestras entradas depende directamente de estos valores.

Pruebas

Aquí estoy probando la precisión del actuador. Vuelve a su lugar decentemente. Luego comencé a mover la varilla un milímetro a la vez. El primer movimiento fue de 0,8 mm en lugar de 1 mm, pero los siguientes 4 se acercaron lo suficiente a 1 mm.  Luego, el movimiento de 4 mm tenía un error de aproximadamente 0,15 mm. 

Debemos notar que la varilla tiene un juego de alrededor de 0,25 mm. Este juego se produce entre el husillo y la tuerca del husillo. Además de eso, probablemente tengamos cierta reacción en los engranajes impresos en 3D, así como en los engranajes del propio motor de CC.  

Si aplicamos una fuerza a la varilla y probamos la precisión ahora, por supuesto, obtendremos un error aún mayor, pero esto se puede mejorar ajustando el controlador PID. 

Sin embargo, eso sería todo por este tutorial. Espero que lo hayas disfrutado y hayas aprendido algo nuevo.


Proceso de manufactura

  1. Réplica DIY Mars Perseverance Rover – Proyecto basado en Arduino
  2. Lo que debe saber sobre la turbina de impulso
  3. Sistema de control, medición y automatización de procesos de alto horno
  4. Comedero para mascotas fácil de construir
  5. ¿Qué es la rugosidad de la superficie? Unidad, gráfico, medida
  6. Guía para el mecanizado de aleaciones de titanio
  7. Diseño para la fabricación:una guía práctica
  8. Principio de funcionamiento de una rectificadora
  9. CluePhone de búsqueda del tesoro
  10. Los pormenores de los alimentadores automáticos de barras
  11. ¿Por qué las piezas de acero deben ser templadas y revenidas? ¿Qué es el efecto?