Movimiento de motor lineal mediante encoder.

#1
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. ...
 
#2
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
 
#5
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
 
#6
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.
 
#7
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:
Arriba