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

Leer PWM, decodificar la entrada del receptor RC y aplicar a prueba de fallos

Componentes y suministros

Arduino UNO
× 1
Micro-servo motor SG90
× 2

Acerca de este proyecto

Este proyecto contiene un código genérico pero eficiente que se puede usar para leer simplemente un receptor RC (o cualquier otra señal PWM) en cualquier pin de entrada de Arduino, y también aplicar un sistema de seguridad en caso de pérdida de la señal del transmisor.

A continuación se muestra un video que muestra un Arduino uno actuando como un servo mezclador usando el código PWMread_RCfailsafe.ino disponible en la parte inferior de esta página.

De manera útil, las funciones en PWMread_RCfailsafe.ino se encargan de los registros de interrupciones por usted y se pueden mover fácilmente entre diferentes proyectos que usan diferentes pines.

En el ejemplo de video a continuación:

  • El a prueba de fallas se activa cuando el receptor no tiene señal del transmisor. el canal del elevador está configurado al máximo y el canal de alerones está configurado en neutral
  • La dirección del servo azul se establece mediante la posición del acelerador
  • El rango de movimiento (velocidades) del servo azul se establece mediante el control deslizante en el costado del transmisor
  • La mezcla se enciende y apaga usando el interruptor de cambio en el transmisor

Contenido

  • ¿Cómo se controlan los servos mediante PWM?
  • Ejemplos de usos de Arduino en modelos / robots RC
  • Descripción general del código:decodifique PWM del receptor RC con seguridad
  • Cómo utilizar PWMread_RCfailsafe.ino
  • Muestra la frecuencia y la velocidad de fotogramas del receptor
  • Ejemplo de mezcla de servo
  • Justificación del enfoque adoptado
  • Limitaciones

¿Cómo se controlan los servos y los controladores de velocidad mediante PWM?

En el resto de este proyecto se asume que comprende las señales PWM que se utilizan para controlar los servos y los controladores de velocidad. Aquí hay un buen video que explica cómo funcionan estas señales de modulación de ancho de pulso (PWM).

También debe tener conocimientos prácticos de:

  • El IDE de Arduino
  • Variables flotantes, booleanas e int
  • Si hay bucles
  • Para bucles
  • Matrices
  • Biblioteca de servos

Ejemplos de usos de Arduino en modelos / robots RC

Solo estará limitado por su imaginación:

  • Aplicar mezcla de servos, encender / apagar luces, controlar bombas / válvulas, configurar secuencias personalizadas ...
  • Cree un controlador (es decir, estabilización de vuelo / piloto automático, control de rumbo, control de altitud / profundidad, nivelador automático, detección y evitación, regreso a casa ...)
  • Haga que su modelo RC responda a una pérdida de señal o voltaje de batería bajo ...
  • Use el mismo transmisor para múltiples modelos / proyectos sin tener que cambiar ninguna configuración o usar una función de memoria de modelo.

Descripción general del código:decodifique PWM del receptor RC con seguridad

Este código mide señales PWM (Modulación de ancho de pulso) usando interrupciones de cambio de pin. Las funciones utilizadas automatizan la configuración de las interrupciones y la extracción de datos de cualquier pin digital o analógico (excluyendo A6 y A7), en el Arduino Uno, Nano o Pro Mini. Esto hace que el código sea fácil de usar incluso para principiantes.

El objetivo principal de este proyecto era crear un receptor RC genérico con un "módulo" a prueba de fallas que se pueda mover rápidamente entre proyectos. Como tal, el código de ejemplo que se muestra en la sección "cómo usar" puede usarse como un medio para lograr un fin.

Nota: este código no funcionará con la serie del software ni con ninguna otra biblioteca que utilice interrupciones de cambio de pines.

Para aquellos interesados ​​en cómo funciona el código:

  • Los pines de entrada se identifican en una matriz. Esta matriz puede tener cualquier longitud.
  • Una función de configuración habilita interrupciones de cambio de pines configurando los registros apropiados para cada pin listado en la matriz de pines.
  • Un cambio de voltaje en cualquiera de los pines seleccionados activará una de las tres Rutas de servicio de interrupción (ISR) dependiendo del registro de puerto al que pertenece el pin ISR (PCINT0_vect) -> Puerto B, ISR (PCINT1_vect) -> Puerto C o ISR (PCINT2_vect) -> Puerto D.
  • Dentro de cada ISR, se utiliza un bucle FOR y declaraciones IF para determinar qué pin ha cambiado y a qué canal RC pertenece. El tiempo de la interrupción se anota mediante el uso de micros () antes de volver al bucle principal ().
  • Los intervalos de tiempo entre los cambios de pines se utilizan para calcular el ancho del pulso y el período de repetición.
  • Las banderas se establecen en cada ISR para indicar cuándo se han recibido nuevos pulsos
  • Luego, las funciones restantes utilizan las banderas para extraer y procesar los datos recopilados por los ISR

El siguiente video de YouTube realizado por Joop Brokking habla de un proyecto diferente que usa el mismo método para conectar un receptor RC a arduino. Durante los primeros 8 minutos, Joop explica claramente cómo use interrupciones de cambio de pin para medir señales PWM de un receptor RC.

Todo este detalle es cuidado por PWMread_RCfailsafe.ino que se puede descargar al final de esta página.

También puede encontrar información útil sobre la manipulación de puertos aquí: https://tronixstuff.com/2011/10/22/tutorial-arduino-port-manipulation/

Además del manejo de interrupciones de cambio de pin, se ha escrito una función dedicada RC_decode () para convertir un ancho de pulso (1000-2000uS) en una señal de control de + -100% desde un transmisor. A prueba de fallas verifica una señal de transmisor válida usando las tolerancias de señal de 10-330Hz y 500-2500uS. Si se pierde la señal, RC_decode () devuelve un valor predeterminado a prueba de fallas.

Los valores de calibración para un transmisor específico y las posiciones a prueba de fallas se pueden configurar para cada canal en PWMread_RCfailsafe.ino

Cómo utilizar PWMread_RCfailsafe.ino

Paso 1: Ejemplo hardware configuración con Arduino Uno

Si sigue la configuración de ejemplo con un Arduino Uno, conecte su receptor de la siguiente manera:(de lo contrario, si está utilizando su propio proyecto, vaya directamente al paso 2)

  • Encienda el receptor usando los pines 5v y GND
  • Conecte los pines de señal del receptor a los pines 2 a 7 en el Arduino usando cables de puente hembra a macho. (Si tiene un receptor de 2 canales, conéctelo solo a los pines 2 y 3)
  • Para el ejemplo del servo mezclador, conecte un cable de señal de servo al pin 9 y el otro al pin 10.

Paso 2:copie PWMread_RCfailsafe.ino en la carpeta de bocetos

Se ha incluido un boceto de ejemplo RC_Read_Example para descargar en la parte inferior de la página. Puede usar esto como boceto principal si sigue los pasos a continuación.

Copie y pegue el archivo PWMread_RCfailsafe.ino en la carpeta que contiene su boceto principal. La próxima vez que abra el boceto en el IDE, aparecerá una segunda pestaña que contiene el código dentro de PWMread_RCfailsafe.ino.

Paso 3:especificar el entrada alfileres

Abra o vuelva a abrir el boceto principal en el IDE de Arduino.

Haga clic en la pestaña PWMread_RCfailsafe, desplácese hacia abajo hasta el título "VARIABLES DEFINIDAS POR EL USUARIO" e ingrese los pines de entrada en la matriz pwmPIN [].

Nota: Se puede utilizar cualquier número de pines y en cualquier orden. Solo tenga en cuenta que cuantas más entradas tenga, más tiempo dedicará el código a abordar la rutina de interrupción. Nota A6 y A7 son pines solo analógicos y no se pueden usar.

El Arduino MEGA no es compatible actualmente, sin embargo, esto podría remediarse fácilmente si existiera el apetito por él.

Nota: el primer elemento en pwmPIN [] es el canal 1, el segundo elemento el canal 2, etc ... si usa todos los canales del receptor, sería una buena idea asegurarse de que los canales del receptor 1 correspondan al canal 1 en pwmPIN [] ...

Paso 4: Revisar el disponible funciones en PWMread_RCfailsafe.ino

Paso 5: Imprimir el pulso ancho datos a serial

Cargue el código RC_Read_Example, encienda su transmisor e imprima los datos de ancho de pulso sin procesar en serie.

La función RC_avail () debe usarse para verificar cuándo se han recibido nuevos datos en todos los canales, y luego usar print_RCpwm () para enviar los datos de ancho de pulso al serial.

Paso 6: Calibre el transmisor

Usar los datos de ancho de pulso impresos en serie a través de print_RCpwm () para modificar manualmente los valores en las matrices RC_min [], RC_mid [] y RC_max [] para calibrar cada canal en el rango + -100%.

Paso 7:imprima los canales calibrados a serial

Comente la función print_RCpwm ()

Utilice la función RC_decode (canal) para calibrar cada canal en el rango + -1.

Luego imprima cada uno de los canales calibrados en serie usando la función decimal2percentage () seguida de Serial.println ("")

Paso 8: Establecer el a prueba de fallas

Ajuste las posiciones a prueba de fallas en la matriz RC_failsafe [] para cada canal (en el rango + -1).

Encienda y apague el transmisor para verificar que el seguro funciona como se desea.

La entrada RC ahora se puede usar en su boceto.

Nota: es posible que deba desactivar cualquier función a prueba de fallas en el receptor; de lo contrario, el arduino no podrá responder a la pérdida de la señal del transmisor.

Muestra la frecuencia y la velocidad de fotogramas del receptor

El período de repetición del pulso del receptor y la frecuencia se pueden imprimir en serie. Verifique que haya nuevos datos disponibles en el canal elegido usando la función PWM_read (número de canal), antes de usar PWM_period () y PWM_freq () para extraer los datos para imprimir. El código de ejemplo está disponible en RC_FrameRate.ino.

Es mejor utilizar el primer canal, ya que será el primer pulso enviado en cada trama del receptor. PWM_read () usa los mismos indicadores que RC_decode (CH), así que asegúrese de llamar primero a PWM_read ().

Vea la captura de pantalla a continuación:

Puede resultar útil conocer el período del receptor, ya que le indica cuánto tiempo tiene el código antes de que llegue el siguiente conjunto de datos. Si RC_avail () no detecta nuevos datos RC después de un tiempo predeterminado, es decir, 21 ms, ejecute RC_decode () para activar el sistema de seguridad y continuar ejecutando el programa (que podría ser un controlador PID) a una frecuencia constante.

Esto se logra en RC_Read_Example.ino mediante la siguiente instrucción if.

  ahora =millis (); if (RC_avail () || ahora - rc_update> 21) rc_update =ahora; // actualiza los datos de entrada RC usando RC_decode () // ejecuta un controlador PID // aplica la mezcla de servos // coloca los servos}  

Ejemplo de mezcla de servo

He incluido RC_ServoMixer_Example.ino para mostrar cómo se pueden mezclar dos canales receptores (en este caso los canales 2 y 3, elevador y alerón). El boceto también muestra un método para configurar la dirección, la velocidad y el recorte secundario del servo. La biblioteca de servos se usa para controlar los servos a través de los pines 9 y 10.

A continuación se muestra una captura de pantalla de la sección de mezcla de servo del código:

La mezcla se logra simplemente sumando y restando los dos canales y limitando la salida al rango de -1 a +1. Al aplicar la mezcla de ascensor y alerón, crea dos salidas, una para cada servo.

mix1 =canal 2 - canal3 (elv - ail)

mix2 =canal 2 + canal3 (elv - ail)

Antes de colocar los servos, deberá convertir la señal + -100% (+ -1) a un ancho de pulso equivalente en microsegundos para el servo. En RC_ServoMixer_Example.ino utilizo una función calc_uS () para hacer esto. Esta función se coloca en la parte inferior del boceto y se muestra en la captura de pantalla a continuación.

La dirección, la frecuencia y el ajuste secundario especificados para cada servo se utilizan para calcular un ancho de pulso apropiado para el servo.

El pulso neutro estándar es 1500uS, y el rango normal a ambos lados del neutro es + -500uS. Esto da un ancho de pulso mínimo de 1000uS (-100%) y un máximo de 2000uS (+ 100%). Por lo tanto, el pulso con las frecuencias, la dirección y el ajuste secundario aplicados se puede calcular de la siguiente manera.

pulso, uS =1500 + (servo_position_% * tasas * dirección + sub recorte) * 500

La dirección del servo, la velocidad y el ajuste secundario pueden ser estáticos o modificados dinámicamente por el boceto en respuesta a una entrada de otro canal del receptor, o por algún otro medio.

Justificación del enfoque adoptado

Es posible leer un receptor RC usando la función pulseIn (PIN, HIGH), sin embargo pulseIn () bloquea el código en loop () mientras espera que un pulso comience y luego termine, desperdiciando un tiempo de procesamiento precioso. Si hay más de una entrada, también se podrían perder los datos.

Para mayor velocidad, es mejor usar la función de interrupción de cambio de pin de Arduino junto con la manipulación directa del puerto para permitir que el código en loop () se ejecute con el mínimo de retraso. Sin embargo, esto es más complicado y requiere más tiempo que simplemente llamar a pulseIn (PIN, HIGH).

Por lo tanto, quería aprovechar las ventajas de ambos mundos escribiendo un código genérico que pudiera mover entre proyectos. Todo lo que se necesita es copiar y pegar un archivo .ino (que contiene las funciones y las rutinas de interrupción) en la carpeta principal de bocetos, especificar los pines de entrada y luego usar las funciones en el boceto.

Limitaciones

El función micros ()

La sincronización de microsegundos en el arduino se lleva a cabo usando la función micros (). Esta función cuenta en pasos de 4uS. Esto significa que tenemos un nivel de precisión de 4 microsegundos cuando medimos los pulsos de 1000-2000uS. Desde un punto de vista práctico, esto es más que adecuado.

Si lo desea, es posible mejorar esta resolución a 0,5 uS utilizando interrupciones del temporizador. ver enlace a continuación:

https://www.instructables.com/id/How-to-get-an-Arduino-micros-function-with-05us-pr/

Eficiencia de PWMread_RCfailsafe.ino

Si usa PWMread_RCfailsafe.ino para leer un receptor de 6 o 9 canales, el 1.4-2.0% del tiempo de procesamiento se dedica a ejecutar las rutinas de interrupción de cambio de pin, lo que yo diría que es más que aceptable.

Sin embargo, siempre es bueno comprender las limitaciones del código y cómo podría acelerarse si fuera necesario.

A continuación se muestra una lista del tiempo que se tarda en ejecutar cada ISR según el número de canales de entrada seleccionados.

1 canal <8uS

2 canales <12uS

3 canales <16uS

4 canales <20uS

5 canales <20uS

6 canales <24uS

Nota: cuantos más canales se utilicen, más tiempo tardará en ejecutarse cada ISR. Esto se debe a que para loopruns a través de cada canal cada vez que se llama al ISR.

Este tiempo adicional (ineficiencia) es insignificante cuando se miden señales RC de baja frecuencia (es decir, 50 Hz).

Además de lo anterior, se necesitan ~ 4uS para ingresar y salir de un ISR. Para un pulso, el ISR se ejecuta dos veces, una al comienzo de un pulso (BAJO a ALTO) y luego nuevamente al final (ALTO a BAJO).

El tiempo necesario para medir 1 pulso cuando se utilizan 6 entradas RC es

2 * (4us para ingresar ISR + 24uS para ejecutar ISR) =2 * 28 =48uS.

Nota: este es el ancho de pulso mínimo que se puede medir.

El tiempo necesario para leer los 6 canales es 288uS (6 * 48uS)

Suponiendo que el período de repetición del receptor es de 20 milisegundos, la interrupción se ejecutará durante el 1,44% (0,000288 / 0,02) del tiempo. Esto es significativamente mejor que usar la función pulseIn (). pulseIn () bloquearía el código hasta por 20 milisegundos para cada pin.

FYI: si el arduino tenía solo 2 entradas RC, entonces el ISR se ejecutará solo el 0.16% del tiempo (0.000032 / 0.02)

Frecuencia máxima práctica ( Hz)

Si usa este código para cualquier otro propósito, sugeriría que la frecuencia máxima práctica sea de 2.5kHz. Esto da 100 pasos de resolución de la función micros () (+ - 0.025kHz).

Si se usa un pin de entrada a esta frecuencia, el 3% del tiempo se gasta en la interrupción, lo que significa que el servicio mínimo que se puede medir es 0.03. Esto equivale a un pulso mínimo de 12uS.

Para frecuencias más altas, reescriba el ISR para que se adapte a su aplicación.

Código

  • PWMread_RCfailsafe
  • RC_Read_Example
  • RC_FrameRate
  • RC_ServoMixer_Example
PWMread_RCfailsafe Arduino
Este archivo .ino contiene las funciones y las rutinas de interrupción de cambio de pin (ISR) que se utilizan para decodificar un receptor RC y aplicar un sistema de seguridad si se pierde la señal del transmisor. Copie y pegue este archivo en la misma carpeta que el boceto principal (cuando abra el boceto, este código aparecerá como una segunda pestaña en el IDE de arduino). Luego siga las instrucciones en el archivo.
 / * Kelvin Nelson 24/07/2019 * * Decodificación de modulación de ancho de pulso (PWM) del receptor RC con seguridad * * Este código contiene funciones fáciles de usar para medir señales de onda cuadrada en cualquier pines arduiuno pro mini, nano o uno, excepto A6 y A7. * El código está diseñado para usarse con receptores RC, pero también podría usarse en la mayoría de las otras aplicaciones de medición PWM como reemplazo directo de pulseIn (PIN, HIGH). * (hasta la fecha no se ha probado a una frecuencia superior a 1 khz o en un mega arduino) * * Un pulso de señal RC se puede convertir de una duración de ancho de pulso (1000-2000uS) en cada pin de entrada en un - + 100 % (- + 1.0) de salida para usar en un boceto. * La calibración para esta conversión más una configuración a prueba de fallas se puede establecer para cada canal. (tolerancias a prueba de fallos 10-330Hz y 500-2500uS). * * Los datos brutos de cada pin también se pueden extraer, es decir, tiempo de pulso, ancho de pulso, longitud del marco, trabajo y frecuencia. * * La configuración es rápida, la organización de este archivo es la siguiente:* * - Descripción general del código * - Lista de funciones * - Cómo usar, incluidos bocetos de ejemplo * - Variables definidas por el usuario -> especificar pines de entrada, transmisor calibración y a prueba de fallos. * - Variables y funciones globales * * DESCRIPCIÓN GENERAL DEL CÓDIGO:* * El código habilita interrupciones de cambio de pin en los pines seleccionados configurando los registros apropiados. * * Un cambio de voltaje en cualquiera de los pines seleccionados activará una de las tres Rutinas de servicio de interrupción, según el registro al que pertenezca el pin. * - ISR (PCINT0_vect), ISR (PCINT1_vect) o ISR (PCINT2_vect) * * Dentro de cada ISR, el código determina qué pin ha cambiado y toma nota del tiempo antes de regresar al bucle principal (). * * Los intervalos de tiempo entre cambios de pines se utilizan para calcular el ancho del pulso y la longitud del cuadro. * * El ISR establece las banderas para indicar cuándo se reciben nuevos pulsos. * * Las banderas se utilizan para extraer y procesar los datos recopilados por cada ISR. * * Aunque no es exactamente igual, este código sigue principios similares a los explicados en este video:https://youtu.be/bENjl1KQbvo * * /// LISTA DE FUNCIONES:// TIPO DE SALIDA NOMBRE DE FUNCIÓN NOTAS // void setup_pwmRead () inicializa la medición PWM usando interrupciones de cambio de pin // DECODIFICACIÓN DEL RECEPTOR RC // booleano RC_avail () devuelve un valor ALTO cuando hay nuevos datos RC disponibles // flotante RC_decode (número de canal) decodifica el canal RC seleccionado en el rango + -100 % y aplica un valor a prueba de fallos .// void print_RCpwm () Imprime los datos sin procesar del canal RC en el puerto serie (utilizado para la calibración) .// MEDICIONES DE PWM GENÉRICAS // booleano PWM_read (número de canal) devuelve un valor ALTO cuando se ha producido un nuevo pulso detectado en un canal en particular. // La función guarda los datos del pulso en variables fuera de las rutinas de interrupción // y se debe llamar justo antes de usar el resto de funciones PWM. // unsigned long PWM_time () devuelve el tiempo al inicio del pulso // float PWM () devuelve el ancho del pulso // float PWM_period () devuelve el tiempo entre pulsos // float PWM_freq () calcula la frecuencia // float PWM_duty () calcula el deber // NOTA:PWM_read (CH) y RC_decode (CH) usan las mismas banderas para detectar cuándo hay nuevos datos disponibles, lo que significa que los datos podrían perderse si ambos se usan en el mismo canal al mismo tiempo. // SUGERENCIA:si desea usar PWM_read (CH) para encontrar la velocidad de cuadros de un canal RC, llámelo antes de RC_decode (CH). La salida de RC_decode (CH) será el valor predeterminado a prueba de fallas .// CÓMO UTILIZAR, incluidos bocetos de ejemplo // bajo el título "VARIABLES DEFINIDAS POR EL USUARIO" en el siguiente código://// Paso 1:ingrese los pines de entrada en la matriz pwmPIN [] ={}. //// - Se puede ingresar cualquier número de pines en pwmPIN [] (pines disponibles 0 - 13 y A0 - A5) // - No es necesario que los pines estén en orden numérico, por ejemplo pwmPIN [] ={A0, 5,6,10,8} para 5 canales, o pwmPIN [] ={A0,5} para 2 canales // - El primer elemento de la matriz es el número de pin para el "canal 1" y el segundo es el pin número para "canal 2" ... etc.// - Todos los pines conectados al receptor RC deben estar al comienzo de la matriz. es decir, los 2 primeros canales podrían ser entradas RC y el 3er canal podría conectarse a otro dispositivo como el pin de eco de un sensor ultrasónico .//// Paso 2:si un receptor RC está conectado a todas las entradas, configure RC_inputs en 0, si no, especifique el número de canales conectados al receptor, es decir, RC_inputs =2; //// Paso 3:calibre su transmisor cargando un boceto simple con este archivo .ino incluido en la carpeta de bocetos e imprima los valores PWM sin procesar a serial (alternativamente copie y pegue las funciones necesarias en el boceto) .// Usando la información del monitor serial actualice manualmente los valores en las matrices RC_min [], RC_mid [], RC_max [] para adaptarse a su transmisor (use tasas completas para obtener la mejor resolución). // un boceto de ejemplo para imprimir los datos PWM del canal RC en serie. / * configuración vacía () {setup_pwmRead (); Serial.begin (9600); } bucle vacío () {if (RC_avail ()) print_RCpwm (); } * /// Paso 4:Elija una posición a prueba de fallas para cada canal, en el rango de -1.0 a +1.0, e ingréselo en la matriz RC_failsafe [] ={} // Nota:si desea que el arduino responda la pérdida de la señal del transmisor, es posible que deba deshabilitar la función de seguridad en su receptor (si tiene una) .// un boceto de ejemplo para verificar el funcionamiento del dispositivo de seguridad y para imprimir los canales calibrados en serie:/ * unsigned long now; // variables de tiempo para actualizar los datos en un intervalo regular unsigned long rc_update; const int canales =6; // especificar el número de canales del receptor float RC_in [canales]; // una matriz para almacenar la entrada calibrada del receptor void setup () {setup_pwmRead (); Serial.begin (9600); } bucle vacío () {ahora =millis (); if (RC_avail () || now - rc_update> 25) {// si los datos RC están disponibles o han pasado 25ms desde la última actualización (ajustar para adaptarse a la velocidad de fotogramas del receptor) rc_update =now; // print_RCpwm (); // descomenta para imprimir datos brutos del receptor al serial para (int i =0; i  =0 &&pwmPIN [i] <=7) pwmPIN_port [i] =2; // el pin pertenece a PCINT2_vect (PUERTO D) else if (pwmPIN [i]> =8 &&pwmPIN [i] <=13) pwmPIN_port [i] =0; // el pin pertenece a PCINT0_vect (PORT B) // convierte el número de pin (es decir, pin 11 o pin A0) a la posición del pin en el registro del puerto. Lo más probable es que haya una mejor manera de hacer esto usando una macro ... // (Leer el estado del pin directamente desde los registros del puerto acelera el código en el ISR) if (pwmPIN [i] ==0 || pwmPIN [i ] ==A0 || pwmPIN [i] ==8) pwmPIN_reg [i] =0b00000001; más si (pwmPIN [i] ==1 || pwmPIN [i] ==A1 || pwmPIN [i] ==9) pwmPIN_reg [i] =0b00000010; más si (pwmPIN [i] ==2 || pwmPIN [i] ==A2 || pwmPIN [i] ==10) pwmPIN_reg [i] =0b00000100; más si (pwmPIN [i] ==3 || pwmPIN [i] ==A3 || pwmPIN [i] ==11) pwmPIN_reg [i] =0b00001000; más si (pwmPIN [i] ==4 || pwmPIN [i] ==A4 || pwmPIN [i] ==12) pwmPIN_reg [i] =0b00010000; más si (pwmPIN [i] ==5 || pwmPIN [i] ==A5 || pwmPIN [i] ==13) pwmPIN_reg [i] =0b00100000; más si (pwmPIN [i] ==6) pwmPIN_reg [i] =0b01000000; si no (pwmPIN [i] ==7) pwmPIN_reg [i] =0b10000000; }} // CONFIGURACIÓN DE INTERRUPCIÓN DE CAMBIO DE PIN void setup_pwmRead () {for (int i =0; i  num_ch) RC_inputs =num_ch; // define el número de pines conectados a un receptor RC. } // RUTINAS DE SERVICIO DE INTERRUPCIÓN (ISR) UTILIZADAS PARA LEER ENTRADA PWM // el PCINT0_vect (registro de puerto B) reacciona a cualquier cambio en los pines D8-13.// el PCINT1_vect (registro de puerto C) "" "" A0-A5. // los registros de puerto PCINT2_vect (D) "" "" D0-7.// se utilizan para acelerar las declaraciones if en código ISR:// https://www.arduino.cc/en/Reference/PortManipulation http ://tronixstuff.com/2011/10/22/tutorial-arduino-port-manipulation/// http://harperjiangnew.blogspot.co.uk/2013/05/arduino-port-manipulation-on-mega-2560 .html// READ INTERRUPTS ON PINS D8-D13:ISR routine detects which pin has changed, and returns PWM pulse width, and pulse repetition period.ISR(PCINT0_vect){ // this function will run if a pin change is detected on portB pciTime =micros(); // Record the time of the PIN change in microseconds for (int i =0; i  RC_inputs) return 0; // if channel number is out of bounds return zero. int i =CH - 1; // determine the pulse width calibration for the RC channel. The default is 1000, 1500 and 2000us. int Min; if(CH <=size_RC_min) Min =RC_min[CH-1]; else Min =1000; int Mid; if(CH <=size_RC_mid) Mid =RC_mid[CH-1]; else Mid =1500; int Max; if(CH <=size_RC_max) Max =RC_max[CH-1]; else Max =2000; float CH_output; if(FAILSAFE(CH) ==HIGH){ // If the RC channel is outside of failsafe tolerances (10-330hz and 500-2500uS) if(CH> size_RC_failsafe) CH_output =0; // and if no failsafe position has been defined, set output to neutral else CH_output =RC_failsafe[i]; // or if defined set the failsafe position } else{ // If the RC signal is valid CH_output =calibrate(PW[i],Min,Mid,Max); // calibrate the pulse width to the range -1 to 1. } return CH_output; // The signal is mapped from a pulsewidth into the range of -1 to +1, using the user defined calibrate() function in this code. // 0 represents neutral or center stick on the transmitter // 1 is full displacement of a control input is one direction (i.e full left rudder) // -1 is full displacement of the control input in the other direction (i.e. full right rudder)}/* * Receiver Calibration */ // NEED TO SPEED UPfloat calibrate(float Rx, int Min, int Mid, int Max){ float calibrated; if (Rx>=Mid) { calibrated =map(Rx, Mid, Max, 0, 1000); // map from 0% to 100% in one direction } else if (Rx ==0) { calibrated =0; // neutral } else { calibrated =map(Rx, Min, Mid, -1000, 0); // map from 0% to -100% in the other direction } return calibrated * 0.001;}// Basic Receiver FAIL SAFE// check for 500-2500us and 10-330Hz (same limits as pololu)boolean FAILSAFE(int CH){ int i =CH-1; boolean failsafe_flag =LOW; if(pwmFlag[i] ==1) // if a new pulse has been measured. { pwmFlag[i] =0; // set flag to zero if(pwmPeriod[i]> 100000) // if time between pulses indicates a pulse rate of less than 10Hz { failsafe_flag =HIGH; } else if(pwmPeriod[i] <3000) // or if time between pulses indicates a pulse rate greater than 330Hz { failsafe_flag =HIGH; } if(PW[i] <500 || PW[i]> 2500) // if pulswidth is outside of the range 500-2500ms { failsafe_flag =HIGH; } } else if (micros() - pwmTimer[i]> 100000) // if there is no new pulswidth measurement within 100ms (10hz) { failsafe_flag =HIGH; } return failsafe_flag; }/* * Quick print function of Rx channel input */void print_RCpwm(){ // display the raw RC Channel PWM Inputs for (int i =0; i =0) Serial.print(" "); if (abs(pc) <100) Serial.print(" "); if (abs(pc) <10) Serial.print(" "); Serial.print(" ");Serial.print(pc);Serial.print("% ");}/* * GENERIC PWM FUNCTIONS */unsigned long pin_time;float pin_pwm;float pin_period;boolean PWM_read(int CH){ if(CH <1 &&CH> num_ch) return false; int i =CH-1; boolean avail =pwmFlag[i]; if (avail ==HIGH){ pwmFlag[i] =LOW; noInterrupts(); pin_time =pwmTimer[i]; pin_pwm =PW[i]; pin_period =pwmPeriod[i]; interrupts(); } return avail;}unsigned long PWM_time(){return pin_time;}float PWM_period(){return pin_period;}float PWM(){return pin_pwm;}float PWM_freq(){ float freq; return freq =1000000 / pin_period; // frequency Hz}float PWM_duty(){ float duty; duty =pin_pwm/pin_period; return duty;}
RC_Read_ExampleArduino
An example sketch used to display raw data in order to calibrate your RC receiver and set your the fail safe. The PWMread_RCfailsafe.ino file should be copied into the same folder in order for the functions to be available.
unsigned long now; // timing variables to update data at a regular interval unsigned long rc_update;const int channels =6; // specify the number of receiver channelsfloat RC_in[channels]; // an array to store the calibrated input from receiver void setup() { setup_pwmRead(); Serial.begin(9600);}void loop() { now =millis(); if(RC_avail() || now - rc_update> 25){ // if RC data is available or 25ms has passed since last update (adjust to be equal or greater than the frame rate of receiver) rc_update =now; print_RCpwm(); // uncommment to print raw data from receiver to serial for (int i =0; i 
RC_FrameRateArduino
Example sketch that prints the frame rate and frequency of an RC Receiver. The PWMread_RCfailsafe.ino file should be copied into the same folder in order for the functions to be available.
void setup() { setup_pwmRead(); Serial.begin(9600);}void loop() { // Print RC receiver frame length and frame rate if (PWM_read(1)){ // if a new pulse is detected on channel 1 Serial.print(PWM_period(),0);Serial.print("uS "); Serial.print(PWM_freq());Serial.println("Hz"); }} 
RC_ServoMixer_ExampleArduino
An servo mixing example. Two channels from a 6 channel are receiver are mixed and sent to two servos controlled using the servo library. The PWMread_RCfailsafe.ino file should be copied into the same folder in order for the functions to be available.
// servo variables#include  // include the servo library to control the servosServo servo1; // name each servo output for use with the servo library Servo servo2; // Each servo must be attached to a pin that has a PWM output// on the arduino uno, nano and pro mini these pins are 3, 5, 6, 9, 10 and 11const int servo1_pin =9; // identify the pins that each servo signal wire is connected toconst int servo2_pin =10;// Select Servo Direction, Rates and Sub-trim (the size of each array must match the number of servos)boolean servo_dir[] ={0,1}; // Direction:0 is normal, 1 is reversefloat servo_rates[] ={1,0.5}; // Rates:range 0 to 2 (1 =+-500us (NORMAL), 2 =+-1000us (MAX)):The amount of servo deflection in both directionsfloat servo_subtrim[] ={0.0,0.0}; // Subtrimrange -1 to +1 (-1 =1000us, 0 =1500us, 1 =2000us):The neutral position of the servoboolean servo_mix_on =true;unsigned long now; // timing variables to update data at a regular interval unsigned long rc_update;// Receiver variablesconst int channels =6; // specify the number of receiver channelsfloat RC_in[channels]; // an array to store the calibrated input from receiver void setup() { servo1.attach(servo1_pin, 500, 2500); // attach the servo library to each servo pin, and define min and max uS values servo2.attach(servo2_pin, 500, 2500); setup_pwmRead(); Serial.begin(9600);}void loop() { now =millis(); if(RC_avail() || now - rc_update> 25){ // if RC data is available or 25ms has passed since last update (adjust to> frame rate of receiver) rc_update =now; print_RCpwm(); // uncommment to print raw data from receiver to serial for (int i =0; i 1) mix1 =1; // limit mixer output to +-1 else if(mix1 <-1) mix1 =-1; if(mix2> 1) mix2 =1; // limit mixer output to +-1 else if(mix2 <-1) mix2 =-1; // Calculate the pulse widths for the servos servo1_uS =calc_uS(mix1, 1); // apply the servo rates, direction and sub_trim for servo 1, and convert to a RC pulsewidth (microseconds, uS) servo2_uS =calc_uS(mix2, 2); // apply the servo rates, direction and sub_trim for servo 2, and convert to a RC pulsewidth (microseconds, uS) } else{ // MIXING OFF servo1_uS =calc_uS(RC_in[1],1); // apply the servo rates, direction and sub_trim for servo 1, and convert to a RC pulsewidth (microseconds, uS) servo2_uS =calc_uS(RC_in[2],2); // apply the servo rates, direction and sub_trim for servo 1, and convert to a RC pulsewidth (microseconds, uS) } servo1.writeMicroseconds(servo1_uS); // write the pulsewidth to the servo. servo2.writeMicroseconds(servo2_uS); // write the pulsewidth to the servo. }}int calc_uS(float cmd, int servo){ // cmd =commanded position +-100% // servo =servo num (to apply correct direction, rates and trim) int i =servo-1; float dir; if(servo_dir[i] ==0) dir =-1; else dir =1; // set the direction of servo travel cmd =1500 + (cmd*servo_rates[i]*dir + servo_subtrim[i])*500; // apply servo rates and sub trim, then convert to a uS value if(cmd> 2500) cmd =2500; // limit pulsewidth to the range 500 to 2500us else if(cmd <500) cmd =500; return cmd;}

Esquemas

This RC Receiver is powered by 5v and ground from the ICSP pins with the 6 signal outputs connected to pins 2-7
Micro servo 1 is powered by 5v pin and ground, with signal wire connected to pin 9
Micro servo 2 powered by 3.3v pin and ground, with signal wired connected to pin 10

Proceso de manufactura

  1. C - Entrada y Salida
  2. Animación LCD y juegos
  3. Voltímetro de bricolaje con Arduino y un teléfono inteligente
  4. Registrador de datos de temperatura y humedad
  5. Cómo leer la temperatura y la humedad en Blynk con DHT11
  6. Python3 y comunicación Arduino
  7. Autómatas celulares basados ​​en Arduino y OLED
  8. Radio FM usando Arduino y RDA8057M
  9. Receptor de radio FM Arduino TEA5767
  10. Sistema de asistencia basado en Arduino y hoja de cálculo de Google
  11. Una entrada analógica aislada para Arduino