PIC controlador Motor de RC (y ejemplo lego robot) (2 / 6 paso)

Paso 2: Software

Este paso iremos a través de cada parte del software y explicar lo que hace. Si no tienen ningún interés en modificar el software y quiero construir la cosa, usted puede ir al siguiente paso. El archivo hexadecimal siempre hará que el proyecto funciona como diseñado.

Configureation básico de periferials de chip
#pragma config OSC = INTIO2, WDT = OFF, LVP = OFF
#include < p18f1320.h >

Esto define el oscilador interno y carga la configuración de la 18F1320, si desea utilizar un pic diferente que esta es una de las cosas que tienes que cambiar

pines de configuración para la entrada PWM
#define ReceiverPin PORTBbits.RB3
#define ReceiverTris TRISBbits.TRISB3

Esto es solo dar un nombre al pin para recibir la señal por lo que es más claro hablar de.

PWM captura de variables
unsigned int PWM1RiseTime = 0; valor del temporizador en el borde de levantamiento de captura
unsigned int PWM1FallTime = 0; valor del temporizador de captura de borde descendente
unsigned int PWM1Width = 0; ancho calculado

unsigned int CH1_width = 0;
unsigned int CH2_width = 0;
unsigned int CH3_width = 0;
unsigned int PWMGap = 0; distancia calculada entre pulsos

char PWM1Edge = 1; borde actualmente monitoreados 1 = aumento, 0 = caer

variables de botón
unsigned char button_1_debounce_wait = 0;

Puesto que la señal PWM del receptor se comunica por enviar impulsos de diferentes variables de la anchura se declaran para sostener estas anchuras, una vez que se calculan.

unsigned char calibration_mode = 0;
#define mode_operate 0
#define mode_CH1_high 1
#define mode_CH1_med 2
#define mode_CH1_low 3
#define mode_CH2_high 4
#define mode_CH2_med 5
#define mode_CH2_low 6

unsigned int limit_CH1_high = 2381;
unsigned int limit_CH1_med = 3307;
unsigned int limit_CH1_low = 4286;

unsigned int limit_CH2_high = 2022;
unsigned int limit_CH2_med = 2946;
unsigned int limit_CH2_low = 3983;
unsigned int CH_temp = 0;

Cuando el modo de calibración está en el sistema se reajuste estos "límites" para adaptarse a la señal. Estos son los valores por defecto, el funcionamiento de la calibración se explicará más adelante.

variables de control del motor
#define Motor_PWM_Rez 16 //number si diferentes velocidades posible hacia adelante y hacia atrás
#define center_buffer 20 //this es la fracción de la gama antes de movimiento

Son constantes que se puede ajustar si está utilizando diversas partes. El búfer de centro es la zona muerta en el centro donde el controlador no hace que el motor do cualquier cosa. El rezolution es cuántos diferentes velocidades el sistema dividirá gama de control en.

unsigned char Motor_Phase = 0; //as ciclos esto a tiempo los motores

unsigned int CH1_range = 2000;
unsigned char Motor_A_Speed = 0; Esta es la velocidad del motor A, % 100 será igual a la rezolution
unsigned char CH1_forward_increment = 10; //the ancho del rango para cada salida de velocidad
unsigned char CH1_reverse_increment = 10;

unsigned int CH2_range = 2000;
unsigned char Motor_B_Speed = 0; Esta es la velocidad del motor A, % 100 será igual a la rezolution
unsigned char CH2_forward_increment = 10; //the ancho del rango para cada salida de velocidad
unsigned char CH2_reverse_increment = 10;

typedef struct
{
signo de motor_A_Direction: 1;
signo de motor_B_Direction: 1;
signo de button_1_last_state: 1;
} PEDACITOS DE;

unsigned char motor_A_inverted = 1; //this relacionados con la calibración
unsigned char motor_B_inverted = 1;
unsigned char motor_calibration_needed = 1;

Bits de BITS volátiles;

variables de tiempo
unsigned char slow_count = 0; Esto se utiliza para crear el escalado temporizador para eventos más lento

La variable anterior será un contador para que una subdivisión de la interrupción de temporizador puede ir sólo cada uno de muchos pasos de temporizador.

configurar interrupción
void low_ISR (void); //prototype
#pragma código low_vector = 0x08 //0X08 es poco 0X18 es alta
void low_interrupt (void) {}
_asm goto low_ISR _endasm
}
código #pragma
#pragma interrupción low_ISR

Esta parte no es la interrupción en sí mismo pero arriba del conjunto para la interrupción que se produzca. La interrupción es un evento que permite algo que se puede activar para que el programa no tiene que ser un gran bucle.

void main
{
OSCCON = 0X72; Reloj de 8MHz
mientras (!. OSCCONbits.IOFS); Esperar a OSC para convertirse en estable

configura timer1
PIR1bits.TMR1IF = 0; borra la bandera de cierre de temporizador 1
T1CONbits.TMR1ON = 1; Encienda el temporizador
T1CONbits.T1CKPS1 = 0; sistema divisor
T1CONbits.T1CKPS0 = 0; sistema divisor

configuración timer2
PIR1bits.TMR2IF = 0; borra la bandera de cierre de temporizador 2
PIE1bits.TMR2IE = 1; habilitar la interrupción
PR2 = 199;
T2CON = 0b00000100; (-) siempre 0 postscale (-) (-) (-) prescaler de encendido-apagado

configurar el CCP1
CCP1CON = 0b0000101; configurar el CCP1 para captura, borde de levantamiento
INTCONbits.PEIE=1; Permitir interrupciones periféricas
PIE1bits.CCP1IE=1; habilita interrupción del CCP1
INTCONbits.GIE=1; permitir la ramificación interrumpir
ReceiverTris = 1; establecer RB3 entrada así que puede trabajar la captura.
TRISBbits.TRISB2 = 1; establecer rb2 para por lo que puede ser utilizado para diferenciar canales

El módulo de captura hace todo el pesado trabajo aquí. Por encima se inicializa para esperar la señal para levantarse, más adelante esto cambiará dinámicamente para captura de anchura de pulso.

configurar puertos
ADCON1 = 0XFF; todo digital
INTCON2bits.RBPU = 0; Puerto b pullups débil en

Estos serán salidas de motor
TRISAbits.TRISA0 = 0;
#define Motor_Pin_A1 LATAbits.LATA0
TRISAbits.TRISA1 = 0;
#define Motor_Pin_A2 LATAbits.LATA1
TRISAbits.TRISA2 = 0;
#define Motor_Pin_B1 LATAbits.LATA2
TRISAbits.TRISA3 = 0;
#define Motor_Pin_B2 LATAbits.LATA3

Estos comandos configurar los pines necesarios para controlar los motores actúan como salidas. Luego los pernos de motor llevan el nombre de fácil acceso.

Estos serán salidas de indicador
TRISAbits.TRISA6 = 0;
TRISAbits.TRISA7 = 0;

se trata de la entrada de señal del servo
TRISBbits.TRISB0 = 1;

inicialmente calibrar las gamas RC
motor_calibration_needed = 1;

while(1)
{
}
}

Mientras bucles mantiene el programa de terminación. No se deje engañar por el hecho de que está vacía. Interrupciones activarán eventos y el reloj sigue funcionando.

A continuación es el inicio de la interrupción de temporizador. Apaga periódicamente a la máxima velocidad que cualquier función requiere, para operaciones rápidas como decidir si es momento de apagar el motor, entonces se subdivide con contadores para operar las funciones que no requieren de tan alta velocidad, tales como control de la entrada y decidir si debe cambiar la velocidad.

void low_ISR(void)
{

Bandera de temporizador 2 (actualmente programado para interrumpir a 10Khz)
if(PIR1bits.TMR2IF == 1)
{
PIR1bits.TMR2IF = 0; borra la bandera de cierre de temporizador 1

Así que en cuanto a no perder el tiempo haciendo cosas más rápidamente que sea necesario (una buena manera de mirar muchos tipos de trabajo) la parte de abajo usa la variable "slow_count" sólo ejecutar cada 100 veces que el bucle exterior se ejecuta.

Esta función se ejecuta en 100 Hz *** withEN
slow_count ++;
if(slow_count > 100)
{
slow_count = 1; //reset cuenta para la próxima vez

Botón de calibración del mango
if(button_1_debounce_wait > 0) {button_1_debounce_wait--;}
if(PORTBbits.RB0 == 0) {}
Si (Bits.button_1_last_state == 0 & & button_1_debounce_wait == 0) //button solo prensado
{
button_1_debounce_wait = 10; //set debounce cuenta
calibration_mode ++;
if(calibration_mode > 6) {calibration_mode = 0;}
}
Bits.button_1_last_state = 1;
}
otra cosa
{
Bits.button_1_last_state = 0;
}
extremo del botón de calibración

A continuación la calibración se aplica realmente. Esto se hace en el modo de operación normal por lo que las luces se apagan ambos. El programa comprueba si el intervalo de calibración es al revés, alta es menor que bajo y viceversa y si así establece una marca para que las direcciones de los motores actuará en consecuencia.

Manejar indicadores Led modo
if(calibration_mode == mode_operate)
{
LATAbits.LATA6 = 0;
LATAbits.LATA7 = 0;

if(motor_calibration_needed == 1)
{
motor_calibration_needed = 0; claro la bandera

calcular las variables de calibración para CH1
if(limit_CH1_low < limit_CH1_high) //speed aumenta a medida que aumenta de número
{
motor_A_inverted = 0;
}
Else / / disminuye la velocidad aumenta como número
{
tan alto es el mayor valor de intercambio
CH_temp = limit_CH1_low;
limit_CH1_low = limit_CH1_high;
limit_CH1_high = CH_temp;

motor_A_inverted = 1;
}

CH1_range = limit_CH1_high-limit_CH1_low;
CH1_forward_increment = (limit_CH1_high-limit_CH1_med-((limit_CH1_high-limit_CH1_med)/center_buffer)) / Motor_PWM_Rez;
CH1_reverse_increment = (limit_CH1_med-limit_CH1_low-((limit_CH1_med-limit_CH1_low)/center_buffer)) / Motor_PWM_Rez;
}

calcular las variables de calibración para CH2
if(limit_CH2_low < limit_CH2_high) //speed aumenta a medida que aumenta de número
{
motor_B_inverted = 0;
}
Else / / disminuye la velocidad aumenta como número
{
tan alto es el mayor valor de intercambio
CH_temp = limit_CH2_low;
limit_CH2_low = limit_CH2_high;
limit_CH2_high = CH_temp;

motor_B_inverted = 1;
}

CH2_range = limit_CH2_high-limit_CH2_low;
CH2_forward_increment = (limit_CH2_high-limit_CH2_med-((limit_CH2_high-limit_CH2_med)/center_buffer)) / Motor_PWM_Rez;
CH2_reverse_increment = (limit_CH2_med-limit_CH2_low-((limit_CH2_med-limit_CH2_low)/center_buffer)) / Motor_PWM_Rez;

}
final de indicadores led modo

Debajo de calibración se maneja. Cada vez que el botón se presiona a los cambios del modo de calibración, indicando que se establece un nuevo límite. El patrón es CH1 completo adelante, medias descanso, completo hacia atrás, entonces el mismo tres posiciones nuevamente en el canal dos. Los indicadores muestran para no en modo de calibración, una en para el avance, el otro para atrás y ambos de medio punto de descanso. No es una interfaz sólida pero hace el trabajo.

calibración
if(calibration_mode == mode_CH1_high)
{

Todas estas cosas LATA están sólo la luz se enciende para indicar el modo del usuario. Como se puede ver realmente no establece los límites cuando se pulsa el botón. Sólo coloca en cualquier lugar están en ese modo, así cuando usted empuja el botón otra vez y ese modo termina, que se mantiene el punto de calibración.

LATAbits.LATA6 = 0;
LATAbits.LATA7 = 1;

limit_CH1_high = CH1_width;

}
if(calibration_mode == mode_CH1_med)
{
LATAbits.LATA6 = 1;
LATAbits.LATA7 = 1;

limit_CH1_med = CH1_width;
}
if(calibration_mode == mode_CH1_low)
{
LATAbits.LATA6 = 1;
LATAbits.LATA7 = 0;

limit_CH1_low = CH1_width;
}
if(calibration_mode == mode_CH2_high)
{
LATAbits.LATA6 = 0;
LATAbits.LATA7 = 1;

limit_CH2_high = CH2_width;
}
if(calibration_mode == mode_CH2_med)
{
LATAbits.LATA6 = 1;
LATAbits.LATA7 = 1;

limit_CH2_med = CH2_width;
}
if(calibration_mode == mode_CH2_low)
{
LATAbits.LATA6 = 1;
LATAbits.LATA7 = 0;

limit_CH2_low = CH2_width;

motor_calibration_needed = 1;
}

Ahora las velocidades del motor necesitan ser calculado. La ecuación obtiene el ancho del pulso para ese motor, decide si está sobre el punto medio o no para decidir la dirección, entonces encuentra tiene rango utilizando la resolución de control del motor dentro de la gama total de anchuras posibles.

calcular la velocidad a del motor
Motor_A_Speed = 0;
if(CH1_width > limit_CH1_med+((limit_CH1_high-limit_CH1_med)/center_buffer)) gama de //upper
{
Motor_A_Speed = (CH1_width-limit_CH1_med-((limit_CH1_high-limit_CH1_med)/center_buffer)) / CH1_forward_increment;
Bits.motor_A_Direction = motor_A_inverted;
}
if(CH1_width < limit_CH1_med-((limit_CH1_med-limit_CH1_low)/center_buffer)) gama de //lower
{
Motor_A_Speed = (limit_CH1_med-CH1_width-((limit_CH1_med-limit_CH1_low)/center_buffer)) / CH1_reverse_increment;
Bits.motor_A_Direction =! motor_A_inverted;
}

calcular la velocidad del motor B
Motor_B_Speed = 0;
if(CH2_width > limit_CH2_med+((limit_CH2_high-limit_CH2_med)/center_buffer)) gama de //upper
{
Motor_B_Speed = (CH2_width-limit_CH2_med-((limit_CH2_high-limit_CH2_med)/center_buffer)) / CH2_forward_increment;
Bits.motor_B_Direction = motor_B_inverted;
}
if(CH2_width < limit_CH2_med-((limit_CH2_med-limit_CH2_low)/center_buffer)) gama de //lower
{
Motor_B_Speed = (limit_CH2_med-CH2_width-((limit_CH2_med-limit_CH2_low)/center_buffer)) / CH2_reverse_increment;
Bits.motor_B_Direction =! motor_B_inverted;
}
fin de calcular la velocidad del motor

} //end de sección de 100 hz

Aquí el si declaración y contador que lo anterior sólo ejecutar a 100Hz han terminado y estamos en la frecuencia de interrupción del contador de tiempo completo. La parte inferior manijas de generar la señal de control del motor de la velocidad calculada anteriormente

pulsos de control al motor
Motor_Phase ++;
if(Motor_Phase > Motor_PWM_Rez) {Motor_Phase = 1;}

Motor A
Si (Motor_A_Speed > = Motor_Phase & & Motor_A_Speed < 20) {}
if(bits.motor_A_Direction == 0) {}
Motor_Pin_A1 = 1;
Motor_Pin_A2 = 0;
}
if(bits.motor_A_Direction == 1) {}
Motor_Pin_A1 = 0;
Motor_Pin_A2 = 1;
}
}
Else {}
Motor_Pin_A1 = 0;
Motor_Pin_A2 = 0;
}

Motor B
Si (Motor_B_Speed > = Motor_Phase & & Motor_B_Speed < 20) {}
if(bits.motor_B_Direction == 0) {}
Motor_Pin_B1 = 1;
Motor_Pin_B2 = 0;
}
if(bits.motor_B_Direction == 1) {}
Motor_Pin_B1 = 0;
Motor_Pin_B2 = 1;
}
}
Else {}
Motor_Pin_B1 = 0;
Motor_Pin_B2 = 0;
}

} //end de interrupción del temporizador

A continuación es el inicio de la interrupción del PCCh. Esta es la parte que se encarga de medir el ancho de pulso. Anteriormente fue creado para ser activado por un flanco ascendente. Cuando detecta el flanco ascendente registrará el tiempo usando CCPR1 cambiará para ver para caer y cambiar la variable PWM1Edge para que coincida con. Cuando detecta caída cambia nuevamente y registra el tiempo.

interrupción de PCCh
if(PIR1bits.CCP1IF == 1)
{
PIR1bits.CCP1IF = 0; claro la bandera
if(PWM1Edge == 1) levantamiento de detección de //if
{
CCP1CON = 0b0000100; //switch para detectar flanco descendente
PWM1Edge = 0; //switch para indicar el borde descendente es el siguiente
PWMGap = CCPR1 - PWM1FallTime; calcular diferencia entre pulso comienza
PWM1RiseTime = CCPR1; //save el valor del temporizador baja para el tiempo de subida

if(PWMGap < 10000) {CH2_width = PWMGap;}

}
else //if detección de caída
{
CCP1CON = 0b0000101; //switch para detectar aumento de borde
PWM1Edge = 1; //switch para indicar el borde de levantamiento es el siguiente
PWM1Width = CCPR1 - PWM1RiseTime; (tiempo de subida del pwm es el momento en que se produjo el ascenso de pwm)
PWM1FallTime = CCPR1; //save el valor del temporizador baja para el tiempo de caída

Realmente necesita entender la lógica detrás de esta parte si necesita modificar el código para trabajar en otros receptores. El receptor traxxas utilicé todos los pulsos pone espalda con espalda. Esto hizo que yo no podía leer a través de un pin porque el conjunto de impulsos era un pulso largo cuando se combina. Por lo que diseñó el programa para que el chip sólo está conectado a cada otra salida, en este caso el servo salidas 1 y 3. De esa manera hay una brecha. La brecha corta (una menos que 10000 según lo detectado por el if declaración abajo) es la intermedia y es la longitud del pulso medio, número de pulso 2. El primer impulso después de la larga distancia es pulso número 1 y el después de la brecha de corto número de pulso 3.

if(PWMGap > 10000) {CH1_width = PWM1Width;}
if(PWMGap < 10000) {CH3_width = PWM1Width;}
}

}
}

No dude en hacer preguntas. El me ayudará a hacer las cosas más claras así que realmente aprecio.

Como ya he mencionado en esa última nota este plan gira en torno a los impulsos que se producen hacia atrás. Algunos receptores les espaciar. Si ese fuera el caso usted no necesita hacer este truco en todos. En cambio usted sólo sabe que después de la larga distancia pulso uno, luego después de cada separación corta adicional estás buscando en el pulso 2, 3, 4 y así sucesivamente. Sólo sería hacer una variable para hacer un seguimiento de cuántos pulsos había capturado desde el boquete pasado y restablecerlo cuando tuvo una larga y, a continuación, utilizar para decidir qué canal atribuye una anchura de pulso capturado a.

Artículos Relacionados

Módulos Arduino - L298N puente H doble controlador Motor

Módulos Arduino - L298N puente H doble controlador Motor

Guía de inicio rápido y sencillo para usar y explorar un módulo de controlador de Motor L298N doble puente H con un Arduino.El modelo en el ejemplo que estoy usando es de Ebay.Materiales necesarios:Módulo de controlador de Motor L298N doble puente H
Mini CNC Arduino basado & Adafruit controlador Motor L293D v1 y 2 de la máquina * Mini Stepper reproductor de CD #1

Mini CNC Arduino basado & Adafruit controlador Motor L293D v1 y 2 de la máquina * Mini Stepper reproductor de CD #1

En este proyecto le mostrará cómo construir fácilmente su propio Arduino Mini CNC Plotter de bajo coste!Para eje X e Y, vamos a utilizar paso a paso, los motores y los carriles de dos dvd/cd-rom! Área de impresión será máximo 4x4cm.Paso 1: El Video e
Entrenador de controlador Motor industrial

Entrenador de controlador Motor industrial

*** el diseño de este voltajes entrenador utiliza extremadamente peligroso y sólo debe utilizarse bajo supervisión cualificada ***El aprendiz eléctrico puede aprender a reconocer algunos de los síntomas más comunes y sus causas encontradas durante la
Reasignación de un UPS muerto en un gabinete de controlador Motor CNC

Reasignación de un UPS muerto en un gabinete de controlador Motor CNC

/ * definiciones de estilos * / tabla. MsoNormalTable {mso-estilo-name: "Tabla Normal"; mso-tstyle-rowband-tamaño: 0; mso-tstyle-colband-tamaño: 0; mso-estilo-noshow:yes; mso-estilo-prioridad: 99; mso-estilo-qformat:yes; mso-estilo-parent: "
Cómo hacer un motor de vacío de lego

Cómo hacer un motor de vacío de lego

todo lo que siempre quería hacer es un motor de lego real de trabajo.así que intenté una y otra vez pero perdidas.pero por lo menos...trabajóasí me sale acerca de lo que yo quería hacer un instructable sobre élasí que aquí está.Si ves un montón de vo
Robot de obstáculos evitando L298N puente H doble controlador Motor y sensor ultrasónico

Robot de obstáculos evitando L298N puente H doble controlador Motor y sensor ultrasónico

¡ Hola chicos!Aquí les dejo algunas imágenes del robot:el hardware necesario:Arduino protoboard.protoboard.sensor de ultrasonidos.2 motores DCcables.Regulador del motor L298N puente h dual.chasis de aluminio.el código de arduino:http://SH.St/PQEQT¡¡B
Znap Lego Robot

Znap Lego Robot

Este tutorial sirve de guía a la construcción y programación el robot monstruo pequeño, feroz y autónoma Znap. A través del proyecto, usted aprenderá no sólo construcción de lego pero EV3 programación. Asegúrese de leer cuidadosamente cada paso, util
Simple y de bajo costo 6 patas araña Lego Robot

Simple y de bajo costo 6 patas araña Lego Robot

Lo siento por el tipo de acometida para este documento.Se trata de un simple 6 piernas, 12 servo mini araña y hacer usa de Lego placa, puede agregar más lego en su diseño final. El costo es de solo 12 servos mini + 3d impreso montaje de Lego tu LegoP
Chasis de LEGO robot de frambuesa Pi

Chasis de LEGO robot de frambuesa Pi

Soy bastante nuevo en Raspberry Pi y uno de los proyectos que quería probar era construir un robot. Así que compré "CamJam Edukit 3: Robótica". Creo que es un kit de la robusteza buena, porque es fácil seguir las hojas de trabajo para ayudar con
LEGO Robot

LEGO Robot

mi cuarto robot de Lego hasta la fecha. No se olvide de favorito y también seguirme ya me ayudan muchos.Paso 1: Parte cuenta Paso 2: Cuerpo y brazos The last pic is of what you should now havePaso 3: cabeza Paso 4: Piernas y pies Make this twicePaso
Como hacer un Lego Robot Mech

Como hacer un Lego Robot Mech

si usted necesita un mech de Lego para destruir una ciudad, luchar contra un malo o cualquier otra cosa, aquí es una buena construcción.Paso 1: materialesPaso 2: cuerpo Paso 3: piernas Paso 4: cabeza Paso 5: Garra brazo Paso 6: El brazo lanzallamas P
LEGO Robot que resuelve un cubo de Rubik

LEGO Robot que resuelve un cubo de Rubik

este robot está hecho de un lego mindstromPaso 1: materiales 1. Lego mindstrom 2. Un ordenador 3. Un cubo de rubikPaso 2: construcción Ir a http://tiltedtwister.com/tiltedtwister2.html y obtener las instrucciones y luego descargar las instrucciones y
Cuatro grados de libertad Lego Robot brazo hecho de dos Robots Thymio

Cuatro grados de libertad Lego Robot brazo hecho de dos Robots Thymio

este grado 4 del brazo de robot de libertad está hecho de dos Thymio Robots y un montón de lego.  Las ruedas pequeñas lego rota delante de los sensores de proximidad para medir la distancia real recorrida.Este brazo robot fue creado por: Dr. Stéphane
Lego Robot de guiado GPS

Lego Robot de guiado GPS

cómo hacer un robot guiado por GPS en 10 minutos o menos.Ver todo el proyecto, paso a paso, en la Web de dexterindustries:http://dexterindustries.com/Project-10MinuteBot-DIGPS.htmlEl robot se puede programar fácilmente con NXT-G, un sencillo lenguaje