- Diagrama de circuito
- Generación de señales PWM en el pin GPIO para control de servomotor
- Programación de PIC16F8771A para brazo robótico
- Simulación del código del brazo robótico PIC
- Diseño de PCB usando EasyEDA
- Cálculo y pedido de muestras en línea
- Funcionamiento del brazo robótico PIC
Desde la línea de montaje de las industrias de fabricación de automóviles hasta los robots de telecirugía en el espacio, los brazos robóticos se encuentran en todas partes. Los mecanismos de estos robots son similares a los de un humano que pueden programarse para una función similar y mayores capacidades. Se pueden usar para realizar acciones repetidas de forma más rápida y precisa que los humanos o se pueden usar en entornos hostiles sin arriesgar la vida humana. Ya hemos construido un brazo robótico de grabación y reproducción con Arduino que podría entrenarse para realizar una tarea en particular y repetirse para siempre.
En este tutorial usaremos el microcontrolador estándar de la industria PIC16F877A de 8 bits para controlar el mismo brazo robótico con potenciómetros. El desafío con este proyecto es que PIC16F877A tiene solo dos pines capaces de PWN, pero necesitamos controlar alrededor de 5 servomotores para nuestro robot que requiere 5 pines PWM individuales. Así que tenemos que utilizar los pines GPIO y generar señales PWM en los pines PIC GPIO usando las interrupciones del temporizador. Ahora, por supuesto, podríamos actualizar a un mejor microcontrolador o usar un IC demultiplexor para hacer las cosas mucho más fáciles aquí. Pero aún así, vale la pena probar este proyecto para la experiencia de aprendizaje.
La estructura mecánica del brazo robótico que estoy usando en este proyecto se imprimió completamente en 3D para mi proyecto anterior; Puede encontrar los archivos de diseño completos y el procedimiento de montaje aquí. Alternativamente, si no tiene una impresora 3D, también puede construir un brazo robótico simple usando cartones como se muestra en el enlace. Suponiendo que de alguna manera se haya apoderado de su brazo robótico, continuemos con el proyecto.
Diagrama de circuito
A continuación se muestra el diagrama de circuito completo para este brazo robótico basado en microcontrolador PIC. Los esquemas se dibujaron con EasyEDA.
El diagrama del circuito es bastante simple; el proyecto completo está alimentado por el adaptador de 12V. Este 12V se convierte luego a + 5V usando dos reguladores de voltaje 7805. Uno está etiquetado como + 5V y el otro está etiquetado como + 5V (2). La razón para tener dos reguladores es que cuando el servo gira, atrae mucha corriente, lo que crea una caída de voltaje. Esta caída de voltaje obliga al PIC a reiniciarse, por lo que no podemos operar tanto el PIC como los servomotores en el mismo riel de + 5V. Entonces, el etiquetado como + 5V se usa para alimentar el microcontrolador PIC, la pantalla LCD y los potenciómetros y una salida de regulador separada que está etiquetada como + 5V (2) se usa para alimentar los servomotores.
Los cinco pines de salida de los potenciómetros que proporcionan un voltaje variable de 0V a 5V están conectados a los pines analógicos An0 a AN4 del PIC. Dado que estamos planeando usar temporizadores para generar PWM, los servomotores se pueden conectar a cualquier pin GPIO. He seleccionado pines de RD2 a RD6 para los servomotores, pero puede ser cualquier GPIO de su elección.
Dado que el programa implica una gran cantidad de depuración, una pantalla LCD de 16x2 también se conecta al puerto B del PIC. Esto mostrará el ciclo de trabajo de los servomotores que se están controlando. Aparte de esto, también he ampliado las conexiones para todos los pines analógicos y GPIO, por si acaso es necesario conectar algún sensor en el futuro. Finalmente, también he conectado el pin H1 del programador para programar directamente el PIC con pickit3 usando la opción de programación ICSP.
Generación de señales PWM en el pin GPIO para control de servomotor
Una vez que el circuito está listo, tenemos que averiguar cómo generar señales PWN en el pin GPIO del PIC para controlar el servomotor. Ya hemos cansado algo similar con el método de interrupción del temporizador y lo hemos logrado. Aquí solo vamos a construir sobre él, por lo que si es nuevo aquí, le recomiendo encarecidamente que lea este tutorial anterior antes de continuar.
Todos los servomotores hobby funcionan con una frecuencia de 50Hz. Lo que significa que un ciclo de pulso completo para un servomotor será 1/50 (F = 1 / T) que es 20 ms. De estos 20ms completos, la señal de control es solo de 0 a 2ms mientras que el resto de la señal está siempre apagada. La siguiente figura muestra cómo el tiempo de ENCENDIDO varía solo de 0 a 2 ms para rotar el motor de 0 grados a 180 grados de la duración total de 20 ms.
Con esto en mente, tenemos que escribir el programa de tal manera que el PIC lea de 0 a 1204 desde el potenciómetro y lo asigne de 0 a 100, que será el ciclo de trabajo del servomotor. Usando este ciclo de trabajo podemos calcular el tiempo de ENCENDIDO del servomotor. Luego, podemos inicializar la interrupción del temporizador para que se desborde a un intervalo regular de manera que actúe de manera similar a la función millis () en Arduino. Con eso, podemos alternar el estado del pin GPIO para que sea alto durante la duración deseada y apagarlo después de 20 ms (un ciclo completo) y luego repetir el mismo proceso. Ahora que hemos entendido la lógica, entremos en el programa.
Programación de PIC16F8771A para brazo robótico
Como siempre, el programa completo con un video se puede encontrar al final de esta página, el código también se puede descargar desde aquí con todos los archivos necesarios. En esta sección discutiremos la lógica detrás del programa. El programa emplea el módulo ADC, el módulo temporizador y el módulo LCD para controlar el brazo robótico. Si no sabe cómo utilizar las funciones de ADC o las funciones de temporizador o cómo conectar una pantalla LCD con PIC, puede recurrir a los enlaces respectivos para aprenderlas. La siguiente explicación se da asumiendo que el lector está familiarizado con estos conceptos.
Configuración del puerto del temporizador 0
La sección más importante del código es configurar el temporizador 0 para que se desborde para cada retraso específico. Las fórmulas para calcular este retraso se pueden dar como
Retraso = ((256-REG_val) * (Prescal * 4)) / Fosc
Al usar el registro OPTION_REG y TMR0, hemos configurado el Timer 0 para que opere con un valor prescalar de 32 y el REG val se establece en 248. La frecuencia de cristal (Fosc) utilizada en nuestro hardware es 20Mhz. Con estos valores, el retraso se puede calcular como
Retraso = ((256-248) * (32 * 4)) / (20000000) = 0,0000512 segundos (o) = 0,05 mseg
Así que ahora hemos configurado el temporizador para que se desborde cada 0,05 ms. El código para hacer lo mismo se da a continuación.
/ ***** Configuración de puerto para temporizador ****** / OPTION_REG = 0b00000100; // Timer0 con frecuencia externa y 32 como prescalar // También habilita PULL UPs TMR0 = 248; // Cargue el valor de tiempo para 0.0001s; delayValue puede estar entre 0-256 solo TMR0IE = 1; // Habilita el bit de interrupción del temporizador en el registro PIE1 GIE = 1; // Habilitar la interrupción global PEIE = 1; // Habilita la interrupción de periféricos / *********** ______ *********** /
De la ventana de control total de 0ms a 2ms del servomotor podemos controlarlo con una resolución de 0.05msec, lo que nos permite tener (2 / 0.05) 40 posiciones diferentes para el motor entre 0 grados a 180 grados. Puede disminuir aún más este valor si su MCU puede soportarlo para obtener más posiciones y un control preciso.
Rutina de servicio de interrupción (ISR)
Ahora que tenemos el temporizador 0 configurado para desbordar cada 0.05ms, tendremos el indicador de interrupción TMR0IF configurado para 0.05ms. Entonces, dentro de la función ISR, podemos restablecer esa bandera e incrementar una variable llamada count en uno. Entonces, ahora esta variable se incrementará en 1 por cada 0.05ms.
void interrupt timer_isr () { if (TMR0IF == 1) // La bandera del temporizador se ha activado debido a un desbordamiento del temporizador -> configurado en desbordamiento por cada 0.05ms { TMR0 = 248; // Carga el temporizador Valor TMR0IF = 0; // Borrar el conteo de banderas de interrupción del temporizador ++; // Cuente los incrementos en 1 por cada 0.05ms }
Cálculo del ciclo de trabajo y el tiempo
A continuación, tenemos que calcular el ciclo de trabajo y el tiempo para los cinco servomotores. Tenemos cinco servomotores, cada uno de los cuales se utiliza para controlar una sección individual del brazo. Así que tenemos que leer el valor ADC de los cinco y calcular el ciclo de trabajo y el tiempo para cada uno.
El valor de ADC estará en el rango de 0 a 1024 que se puede convertir a un ciclo de trabajo de 0% a 100% simplemente multiplicando 0.0976 (100/1024 = 0.0976) por el valor obtenido. Este ciclo de trabajo de 0 a 100% se debe convertir a tiempo ON. Sabemos que al 100% del ciclo de trabajo, el tiempo de ENCENDIDO debe ser de 2 ms (para 180 grados), por lo que multiplicar 0.02 (2/100 = 0.02) convertirá el ciclo de trabajo de 0 a 100 en 0 a 2 ms. Pero luego nuestro recuento de variables de temporizador está configurado para aumentar una vez por cada 0.05ms. Esto significa que el valor de la cuenta será 20 (1 / 0.05 = 20) por cada 1 ms. Entonces tenemos que multiplicar 20 por 0.02 para calcular el tiempo exacto para nuestro programa que nos dará el valor 0.4 (0.02 * 20 = 0.4). El código para el mismo se muestra a continuación, puede verlo repetido 5 veces para los 5 potes usando un bucle for. Los valores resultantes se almacenan en la matriz T_ON.
for (int pot_num = 0; pot_num <= 3; pot_num ++) { int Pev_val = T_ON; POT_val = (ADC_Read (pot_num)); // Leer el valor de POT usando ADC Duty_cycle = (POT_val * 0.0976); // Asignar 0 a 1024 a 0 a 100 T_ON = Duty_cycle * 0.4; // 20 * 0.02
Seleccionar qué motor rotar
No podemos controlar los cinco motores juntos, ya que hará que el código ISR sea pesado y ralentice todo el microcontrolador. Entonces tenemos que girar solo un servomotor a la vez. Para seleccionar qué servo rotar, el microcontrolador monitorea el tiempo de encendido de los cinco servomotores y lo compara con su tiempo anterior. Si hay un cambio en el tiempo de ENCENDIDO, podemos concluir que el servo en particular debe moverse. El código para el mismo se muestra a continuación.
if (T_ON! = Pev_val) { Lcd_Clear (); servo = pot_num; Lcd_Set_Cursor (2,11); Lcd_Print_String ("S:"); Lcd_Print_Char (servo + '0'); if (pot_num == 0) {Lcd_Set_Cursor (1,1); Lcd_Print_String ("A:");} más si (pot_num == 1) {Lcd_Set_Cursor (1,6); Lcd_Print_String ("B:");} más si (pot_num == 2) {Lcd_Set_Cursor (1,11); Lcd_Print_String ("C:");} más si (pot_num == 3) {Lcd_Set_Cursor (2,1); Lcd_Print_String ("D:");} más si (pot_num == 4) {Lcd_Set_Cursor (2,6); Lcd_Print_String ("E:");} char d2 = (Duty_cycle)% 10; char d1 = (Duty_cycle / 10)% 10; Lcd_Print_Char (d1 + '0'); Lcd_Print_Char (d2 + '0');
También imprimimos el ciclo de trabajo del servo en la pantalla LCD para que el usuario pueda conocer su posición actual. Según el cambio en el tiempo de encendido, el servo variable se actualiza con números del 0 al 4, cada uno de los cuales representa motores individuales.
Controlar el servomotor dentro del ISR
Dentro del ISR tenemos el recuento de variables que se incrementa por cada 0.05ms, esto significa que por cada 1ms la variable se incrementará en 20. Usando esto tenemos que controlar los pines para producir la señal PWM. Si el valor del recuento es menor que el tiempo de encendido, entonces el GPIO de ese motor se enciende usando la siguiente línea
PORTD = PORTD - código_servo;
Aquí, la matriz servo_code tiene el detalle de los pines de los cinco servomotores y, según el valor en el servo variable, se utilizará el código para ese servomotor en particular. Entonces es lógicamente OR (-) con bits PORTD existentes para que no perturbemos los valores de otro motor y actualicemos solo este motor en particular. Del mismo modo para apagar el pin
PORTD = PORTD & ~ (servo_code);
Hemos invertido el valor del bit usando el operador lógico inverso (~) y luego hemos realizado una operación Y (&) en el PORTD para apagar solo el pin deseado mientras dejamos los otros pines en su estado anterior. El fragmento de código completo se muestra a continuación.
void interrupt timer_isr () { if (TMR0IF == 1) // La bandera del temporizador se ha activado debido a un desbordamiento del temporizador -> configurado en desbordamiento por cada 0.05ms { TMR0 = 248; // Carga el temporizador Valor TMR0IF = 0; // Borrar el conteo de banderas de interrupción del temporizador ++; // Contar incrementos en 1 por cada 0.05ms -> el conteo será 20 por cada 1ms (0.05 / 1 = 20)) } int servo_code = {0b01000000, 0b00100000, 0b00010000, 0b00001000, 0b00000100}; si (cuenta> = 20 * 20) cuenta = 0; if (cuenta <= (T_ON)) PORTD = PORTD - servo_code; más PORTD = PORTD & ~ (servo_code); }
Sabemos que el ciclo total tiene que durar 20 ms antes de que el pin GPIO se vuelva a encender. Entonces, verificamos si el conteo ha excedido los 20ms comparando el valor del conteo con 400 (el mismo cálculo que se discutió anteriormente) y si es así, tenemos que inicializar el conteo para que sea cero nuevamente.
Simulación del código del brazo robótico PIC
Siempre es mejor simular el código antes de llevarlo al hardware real. Así que usé Proteus para simular mi código y verifiqué que funcionaba correctamente. El circuito utilizado para la simulación se muestra a continuación. Hemos utilizado un osciloscopio para comprobar si las señales PWM se están generando según sea necesario. También podemos verificar si el LCD y los servomotores están girando como se esperaba.
Como se puede ver en la pantalla aparece el ciclo de trabajo del motor D a ser 07 en función del valor olla que es el 3 rd motor. De manera similar, si se mueve otra olla, el ciclo de trabajo de esa olla y su número de motor se mostrarán en la pantalla LCD. La señal PWM que se muestra en el osciloscopio se muestra a continuación.
El período total del ciclo se mide en 22,2 ms utilizando la opción del cursor en el osciloscopio, que está muy cerca de los 20 ms deseados. Finalmente estamos seguros de que el código funciona, así que para continuar con el circuito podemos soldarlo en una placa perf o usar una PCB. No funcionará fácilmente en la placa de pruebas porque el POT siempre tiende a dar algunos problemas debido a conexiones deficientes.
Diseño de PCB usando EasyEDA
Para diseñar este brazo robótico PIC, hemos elegido la herramienta EDA en línea llamada EasyEDA. Lo he estado usando durante mucho tiempo y lo encuentro muy conveniente debido a su gran disponibilidad de espacio y su naturaleza fácil de usar. Después de diseñar la PCB, podemos solicitar las muestras de PCB mediante sus servicios de fabricación de PCB de bajo costo. También ofrecen un servicio de abastecimiento de componentes donde tienen un gran stock de componentes electrónicos y los usuarios pueden solicitar los componentes necesarios junto con el pedido de PCB.
Mientras diseña sus circuitos y PCB, también puede hacer públicos sus diseños de circuitos y PCB para que otros usuarios puedan copiarlos o editarlos y puedan beneficiarse de su trabajo, también hemos hecho públicos todos nuestros diseños de circuitos y PCB para este circuito, verifique el siguiente enlace:
easyeda.com/circuitdigest/pic-development-board-for-robotic-arm
Usando este enlace puede pedir directamente el mismo PCB que estamos usando en este proyecto y usarlo. Una vez que se completa el diseño, la placa se puede ver como un modelo 3D que será de gran ayuda para visualizar cómo se vería la placa después de la fabricación. A continuación se muestra el modelo 3D de la placa que estamos utilizando. Aparte de esto, también puede ver la capa superior e inferior del tablero para verificar si la pantalla resbaladiza es la esperada.
Cálculo y pedido de muestras en línea
Después de completar el diseño de este PIC Robot PCB, puede solicitar el PCB a través de JLCPCB.com. Para pedir el PCB de JLCPCB, necesita Gerber File. Para descargar archivos Gerber de su PCB, simplemente haga clic en el botón Generar archivo de fabricación en la página del editor EasyEDA, luego descargue el archivo Gerber desde allí o puede hacer clic en Solicitar en JLCPCB como se muestra en la imagen de abajo. Esto lo redireccionará a JLCPCB.com, donde puede seleccionar la cantidad de PCB que desea pedir, cuántas capas de cobre necesita, el grosor de la PCB, el peso del cobre e incluso el color de la PCB, como la instantánea que se muestra a continuación:
Una vez que haya seleccionado todas las opciones, haga clic en "Guardar en el carrito" y luego lo llevará a la página donde puede cargar su archivo Gerber que hemos descargado de EasyEDA. Sube tu archivo Gerber y haz clic en "Guardar en el carrito". Y finalmente haga clic en Checkout Securely para completar su pedido, luego obtendrá sus PCB unos días después. Están fabricando la PCB a un precio muy bajo, que es de $ 2. Su tiempo de construcción también es muy inferior, que es de 48 horas con una entrega de DHL de 3-5 días, básicamente obtendrá sus PCB dentro de una semana de realizar el pedido.
Después de pedir la PCB, puede verificar el progreso de producción de su PCB con fecha y hora. Lo verifica yendo a la página Cuenta y haciendo clic en "Progreso de producción".
Después de unos días de ordenar PCB, obtuve las muestras de PCB en un buen empaque como se muestra en las imágenes a continuación.
Y después de obtener estas piezas, he soldado todos los componentes necesarios sobre el PCB. También soldé directamente el POT directamente en lugar de usar cables de conexión porque los cables hembra a hembra que usé inicialmente daban voltajes de salida analógicos extraños probablemente debido a contactos sueltos. Una vez que todos los componentes estuvieron ensamblados, mi PCB se veía así.
Es posible que haya notado que solo hay un 7805 en esta placa. Eso se debe a que inicialmente pensé que podría salirme con la mía con solo el regulador para alimentar tanto el PIC como el servomotor y luego me di cuenta de que necesitaba dos. Así que he usado un circuito externo para alimentar los servomotores a través de los cables verdes que ves aquí.
Sin embargo, no tienes que preocuparte mucho por eso; He realizado los cambios en la PCB ahora. Puede hacer uso de la PCB modificada y soldar ambos reguladores a bordo.
Funcionamiento del brazo robótico PIC
Después de todo el trabajo agotador, es hora de dar sus frutos. Suelde todos los componentes de la placa y cargue el programa en el controlador PIC. El código completo se proporciona a continuación o se puede descargar desde aquí. El conector de programación provisto en la placa debería ayudarlo a cargar el programa directamente usando Pickit 3 sin mucha molestia. Una vez que se carga el programa, debería ver la pantalla LCD mostrando el servo que se está controlando actualmente. Para obtener más información sobre la programación del microcontrolador PIC, simplemente siga el tutorial anterior.
Desde allí, simplemente puede girar el potenciómetro y verificar cómo responden los servomotores a cada potenciómetro. Una vez que comprenda el formato, puede controlar el brazo robótico para realizar cualquier acción que necesite para realizar y divertirse. Puede encontrar el funcionamiento completo del proyecto en el video vinculado a continuación.
Eso es, chicos, espero que hayan entendido el proyecto y hayan aprendido algo nuevo de él. Si tiene alguna pregunta, déjela en la sección de comentarios o utilice los foros para otras discusiones técnicas.