Movimiento de motor lineal mediante encoder.

Hola...

Si alguien de ustedes me pudiera ayudar necesito que mediante un encoder mueva un motor lineal y por medio del modulo de conversion analgocio-digital establecer un fin y un inicio para no forzar los motores.

Código:
/* Librerias*/
#include <xc.h>           // Libreria de lenguaje XC8
#include <pic18.h>        // Libreria de pic
#include <stdio.h>        // Libreria defualt
#include <stdint.h>       // Libreria default
#include <stdbool.h>      // Libreria de lenguaje booleano
#include <delays.h>       // Libreria de retraso
#include <plib/adc.h>     // Libreria analogica
//#include "System.h"     // Libreria de frecuencia de trabajo
//#include "User.h"       // Libreria de usuario
#include <plib/pwm.h>     // Libreria PWM
#include <plib/timers.h>  // Libreria de temporizadores
#include <plib/pconfig.h> // Libreria de configuracion
#include <stdlib.h>       // Libreria para convertir
//******************************************************************************
//#define XTAL_FREQ 20000000;   // Seleccionamos el Oscilador en 20 Mhz
/************************************************************************************/
/**
 * Descripción: Configura el pic para que utilice el oscilador
 * a 20Mhz
 *configuration_bits.c: Programación de los bits de configuración del sistema.
 */
// PIC18F26K80 Configuration Bit Settings
// \'C\' source line config statements
// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.
// CONFIG1L
#pragma config RETEN = OFF      // VREG Sleep Enable bit (Ultra low-power regulator is Disabled (Controlled by REGSLP bit))
#pragma config INTOSCSEL = HIGH // LF-INTOSC Low-power Enable bit (LF-INTOSC in High-power mode during Sleep)
#pragma config SOSCSEL = DIG    // SOSC Power Selection and mode Configuration bits (Digital (SCLKI) mode)
#pragma config XINST = ON       // Extended Instruction Set (Enabled)
// CONFIG1H
#pragma config FOSC = HS2    // Oscillator INTIO2(Internal RC oscillator)HS2
#pragma config PLLCFG = OFF     // PLL x4 Enable bit (Disabled)
#pragma config FCMEN = OFF      // Fail-Safe Clock Monitor (Disabled)
#pragma config IESO = OFF       // Internal External Oscillator Switch Over Mode (Disabled)
// CONFIG2L
#pragma config PWRTEN = OFF     // Power Up Timer (Disabled)
#pragma config BOREN = OFF      // Brown Out Detect (Disabled in hardware, SBOREN disabled)
#pragma config BORV = 3         // Brown-out Reset Voltage bits (1.8V)
#pragma config BORPWR = ZPBORMV // BORMV Power level (ZPBORMV instead of BORMV is selected)
// CONFIG2H
#pragma config WDTEN = OFF      // Watchdog Timer (WDT disabled in hardware; SWDTEN bit disabled)
#pragma config WDTPS = 1048576  // Watchdog Postscaler (1:1048576)
// CONFIG3H
#pragma config CANMX = PORTC    // ECAN Mux bit (ECAN TX and RX pins are located on RB2 and RB3, respectively)
#pragma config MSSPMSK = MSK7   // MSSP address masking (7 Bit address masking mode)
#pragma config MCLRE = ON       // Master Clear Enable (MCLR Enabled, RE3 Disabled)
// CONFIG4L
#pragma config STVREN = OFF      // Stack Overflow Reset (Enabled)
#pragma config BBSIZ = BB1K     // Boot Block Size (2K word Boot Block size)
// CONFIG5L
#pragma config CP0 = OFF        // Code Protect 00800-03FFF (Disabled)
#pragma config CP1 = OFF        // Code Protect 04000-07FFF (Disabled)
#pragma config CP2 = OFF        // Code Protect 08000-0BFFF (Disabled)
#pragma config CP3 = OFF        // Code Protect 0C000-0FFFF (Disabled)
// CONFIG5H
#pragma config CPB = OFF        // Code Protect Boot (Disabled)
#pragma config CPD = OFF        // Data EE Read Protect (Disabled)
// CONFIG6L
#pragma config WRT0 = OFF       // Table Write Protect 00800-03FFF (Disabled)
#pragma config WRT1 = OFF       // Table Write Protect 04000-07FFF (Disabled)
#pragma config WRT2 = OFF       // Table Write Protect 08000-0BFFF (Disabled)
#pragma config WRT3 = OFF       // Table Write Protect 0C000-0FFFF (Disabled)
// CONFIG6H
#pragma config WRTC = OFF       // Config. Write Protect (Disabled)
#pragma config WRTB = OFF       // Table Write Protect Boot (Disabled)
#pragma config WRTD = OFF       // Data EE Write Protect (Disabled)
// CONFIG7L
#pragma config EBTR0 = OFF      // Table Read Protect 00800-03FFF (Disabled)
#pragma config EBTR1 = OFF      // Table Read Protect 04000-07FFF (Disabled)
#pragma config EBTR2 = OFF      // Table Read Protect 08000-0BFFF (Disabled)
#pragma config EBTR3 = OFF      // Table Read Protect 0C000-0FFFF (Disabled)
// CONFIG7H
#pragma config EBTRB = OFF      // Table Read Protect Boot (Disabled)
/**********************************************************************************/
/*Asignacion de variables de entradas digitales*/
#define INT_0   PORTBbits.RB0 // Interruptor RB0 "CENTRAL CSL (Pedestal)-MAP()"
#define INT_1   PORTBbits.RB1 // Interruptor RB1 "CENTRAL PANEL INST (Panel central de instrumentos)-FLOOR/PEDAL()"
#define INT_2   PORTBbits.RB2 // Interruptor RB2 "UPPER PANEL FWD (Panel del techo)-INST()"
#define INT_3   PORTBbits.RB3 // Interruptor RB3 "UPPER PANEL RWD (Cortacircuitos)-LATL CSL()"
#define INT_4   PORTBbits.RB4 // Interruptor RB4 "N/A-READING()"
#define INT_5   PORTBbits.RB5 // Interruptor RB5 "N/A-PANEL()"
/*Asignacion de variables de salidas digitales*/
#define STATUS  PORTCbits.RC0 // Led "STATUS" se encuentra conectado en RC0
#define ERROR   PORTCbits.RC1 // Led "ERROR" se encuentra conectado en RC1
#define PWM_CE  TRISCbits.TRISC2 // La CARATULA se encuentra conectada en RC2 PWM CCP2
/*Asignacion de variables de entradas analogicas*/
#define AN_0    PORTAbits.RA0 // Entrada analogica 0 UPPER PANEL FWD (Panel de techo)-INST(Panel de instrumentos piloto y copiloto)
#define ENA     PORTAbits.RA1 // Entrada analogica 1 UPPER PANEL RWD (Cortacircuitos)-LATL CSL(Consola de piloto y copiloto)
#define DIR     PORTAbits.RA2 // Entrada analogica 2 CENTRAL PANEL INST (Panel central de instrumentos)-PANEL(Luces tubulares)
#define ENA1    PORTBbits.RB5
#define AN_3    PORTAbits.RA3 // Entrada analogica 3 CENTRAL CSL (Pedestal)-N/A

//******************************************************************************
/*Declaracion de funciones*/
void interrupt encoder(void);
void datos ();
void ADC();
//******************************************************************************
/*Declaración de variables*/
unsigned char i = 0; //variable para usar en el contador. (al ser de tipo char admite hasta 256 valores)
int adc = 0;
int adc1 = 0;
//******************************************************************************
/*Programa principal*/
int main(void)
{
    //ConfigureOscillator(); // Llama a funcion para configurar el oscilador a 20Mhz
    //******************************************************************************
    /*Habilitación y deshabilitación de entradas analogicas*/
    ANCON0 = 0x00; // Se habilita RA0-RA3 como analogicas, las demas digitales
    ANCON1 = 0x00; // Se configuran todas digitales
    /*Configuracion de entradas analogicas*/
    PORTA = 0x00;  // Inicializa puerto A
    LATA = 0x00;   // Limpia puerto A
    TRISA = 0x00;  // se habilita RA0-RA3 como analogicas y las demas digitales
    /*Configuración de entradas digitales PORTB*/
    PORTB = 0x00;  // Inicializa puerto B
    LATB = 0x00;   // Limpia puerto B
    TRISB = 0xFF;  // TRISB como Entradas "1"
    /*Configuración de salidas digitales PORTC*/
    PORTC = 0x00;  // Inicializa puerto C
    LATC = 0x00;   // Limpia puerto C
    TRISC = 0xC0;  // CANTX-RC6, CANRX-RC7, PWM-RC2, ERROR-RC1 STATUS-RC0
    //******************************************************************************
    /*Programa en run*/
    PWM_CE = 0;        // Comprobacion de caratula electronica
    STATUS = 0;        // Programa en ejecucion
    ERROR = 1;         // Comprobacion de programa
    Delay10KTCYx(255); // Retardo para esperar que pase cualquier transitorio
    Delay10KTCYx(255);
    ERROR = 0;         // Error
    //******************************************************************************
    /*bucle principal*/
    while(true){
        // funcion de inicializacion del la interrupción

        INTCONbits.GIE = 1;     //habilitamos todas las interrupcione
        INTCON2bits.INTEDG3 = 1; //Esperamos un cambio por flanco de subida.
        INTCON2bits.INT3IP = 1; //Prioridad de interrupcion
        INTCON3bits.INT3IE = 1;
        INTCON3bits.INT3IF = 0;    //Inicialmente no se ha producido una interrupcion.

        datos ();
        interrupt encoder (); //LLama a lectura de encoder
        //ADC ();  
        //Delay10KTCYx(5); // Retardo para esperar que pase cualquier transitorio
        if (i <= 250){
            CCPR2L = i; //Asignacion de periodo
        }
        else{
            i = 0;
        }

        CCP2CON = 0x3F;
        T2CON = 0x7F;
        PR2 = 0xFF;
        
    } // Fin de while principal
} // Fin de main

/*******
 *********************************************************************/
/* Inicia la conversión ADC */
void ADC (void){

    ADCON0bits.CHS0 = 0;     //Seleccionamos el Canal 0
    ADCON0bits.CHS1 = 0;
    ADCON0bits.CHS2 = 0;
    ADCON0bits.CHS3 = 0;
    ADCON0bits.CHS4 = 0;

    ADCON2bits.ACQT0 = 0;    //Seleccionamos el TAD en 16
    ADCON2bits.ACQT1 = 1;
    ADCON2bits.ACQT2 = 1;

    ADCON2bits.ADCS0 = 0;    //Seleccionamos el FOSC en 64
    ADCON2bits.ADCS1 = 1;
    ADCON2bits.ADCS2 = 1;

    ADCON2bits.ADFM = 1;     // Justificamos el resultado a la derecha

while(1){

    ADCON0bits.ADON=1;       //encendemos ADC
    ADCON0bits.GO=1;         //lanzamos la conversión
    while(ADCON0bits.GO);    //esperamos a que acabe la conversión
    ADCON0bits.ADON=0;       //apagamos el ADC
    adc=ADRESH;              //guardamos la parte alta del resultado
    adc=adc<<8;              //recorremos los bits a la derecha
    adc1=adc+ADRESL;         //añadimos la parte alta del resultado    
}
}
/******************************************************************************/
//INTERRUPCION POR CAMBIO DE ESTADO EN RB0 PARA DETECCION DE ENCODER ROTATIVO
void datos (void){
if (INT_1 == 0 & INT_3 == 0 || INT_1 == 1 & INT_3 == 1){
    STATUS = 1;
    Delay10KTCYx(5); // Retardo para esperar que pase cualquier transitorio
    STATUS = 0;
    }
}
void interrupt encoder(void)
{
    INTCONbits.GIE = 0;            //Se deshabilita el resto de interrupciones para que no molesten
    if ( INTCON3bits.INT3IF == 1 ){     //si se ha producido interrupción por entrada en RB0
        INTCON3bits.INT3IF = 0;       // Poner bandera de control a 0.
        if(INT_1 == 0){
            INTCON2bits.INTEDG3 = 0; //si estamos "arriba" detectaremos por flanco de bajada en la siguiente int.
            if (INT_1 == 0 & INT_3 == 0 || INT_1 == 1 & INT_3 == 1 || INT_1 == 0 & INT_3 == 1 || adc1>200 & adc1<750) //si RB3 es 1, incrementamos.
            i = i++;
            STATUS = 1;
            DIR = 1;
            ENA = 0;
            Delay10KTCYx(2); // Retardo para esperar que pase cualquier transitorio
            STATUS = 0;
            ENA = 1;
            }
        else{          //si RB0=0
            INTCON2bits.INTEDG3 = 1;    //si estamos abajo, detectaremos por flanco de subida en la siguiente int.
            if (INT_1 == 0 & INT_3 == 0 || INT_1 == 1 & INT_3 == 1 || INT_1 == 0 & INT_3 == 1 || adc1>200 & adc1<750) //si RB3 es 1, decrementamos.
            i = i--;
            ERROR = 1;
            DIR = 0;
            ENA = 0;
            Delay10KTCYx(2); // Retardo para esperar que pase cualquier transitorio
            ERROR = 0;
            ENA= 1;
        
        }
    }
    INTCONbits.GIE = 1;                //se habilitan las interrupciones de nuevo.

Hasta ahora llevo esto pero al activar la parte del conversor analogico-digital el motor no funciona, por eso la tengo comentada. ...
 
bueno no es que no quiera darte el codigo pero me da mucha flojera escribir

pero es muy simple

con el ADC mides un potenciometro en volts es decir 0 a 5v nada mas

y con un puente H y algo de PWM puedes hacer que gire de izquierda a derecha , el PWM sirve como variador de velocidad

el potenciometro debe estar mecanicamente acoplado al motor asi conoces donde se encuentra el motor

cuando mida algo cercano a los 0v paras
 
si usas encoder puedes detectar cambios por interrupcion en RB0
y si usas un potenciometro lo puedes hacer con el ADC

cualquiera de las 2 es valida pero con el potenciometro se obtiene un control parecido al servomotor
 
Hola, el encoder es para definir el sentido y la velocidad del motor lineal el motor cuenta con retroalimentacion por potenciometro, con el adc necesito poder leer los valores del pot para poder definir un inicio y un final para el motor. si me puedes ayudar te lo agradeceria mucho.
 
si usas encoder puedes detectar cambios por interrupcion en RB0
y si usas un potenciometro lo puedes hacer con el ADC

cualquiera de las 2 es valida pero con el potenciometro se obtiene un control parecido al servomotor

Hola. Disculpa si te molesto pero necesito ayuda. :cry:
El potenciómetro lo traen integrado los motores con el módulo ADC, sólo tengo que hacer un final y un comienzo, porque cuando activas el motor con el encoder, lo giras y giras y no se detiene.

Es lo que necesito. Si me pudieras ayudar te lo agradecería mucho, ya que he intentado todo lo poco que sé de programación y no me queda.

Espero puedas ayudarme.
 
Última edición por un moderador:
Atrás
Arriba