¿Los dos codificadores conectados a un microcontrolador interfieren entre sí?

4

Conecté dos codificadores rotatorios AMT 103 (montados en dos motores de CC separados) a un dspic30f4011 y leí los valores utilizando interrupciones (en lugar de qei, ya que el dspic solo tiene uno). Sin embargo, el error en los valores aumenta cuanto más lejos y más rápido vamos al ejecutar los motores simultáneamente. Una de las teorías es que dado que las interrupciones tienen diferentes prioridades, una de ellas anula la otra y provoca el error, tenga en cuenta que cuando solo se ejecuta un motor no tenemos un error. ¿Esto está causando el error? Si es así, ¿cómo se puede arreglar? ¿Se solucionará esto con un qei y una interrupción? Aquí está el código dspic:

#include "p30f4011.h"
#include <delay.h>
#include <stdlib.h>
#include <math.h>

_FWDT(WDT_OFF)

#define InterruptFlag0_A    IFS0bits.INT0IF //Rising Edge on Signal A, Encoder 1
#define InterruptFlag1_A    IFS1bits.INT1IF //Rising Edge on Signal A, Encoder 2
#define Encoder0_B  PORTBbits.RB0 // Signal B of Encoder 1
#define Encoder1_B  PORTBbits.RB1 // Signal B of Encoder 2

//Variables for Calculations
long T1=0;
int counter=0;
int NR=0;
long T2=0;
int counterone=0;
int NRone=0;
long i;
//-------------------------


int main()
{
    ADCON1=0x0F;//digital
    TRISBbits.TRISB0=1;//RA inputs
    TRISBbits.TRISB1=1;//RA inputs

    //Interrupts init
    IFS1bits.INT1IF = 0;    /*Reset INT1 interrupt flag */
    IEC1bits.INT1IE = 1;    /*Enable INT1 Interrupt Service Routine */
    IFS0bits.INT0IF = 0;    /*Reset INT1 interrupt flag */
    IEC0bits.INT0IE = 1;    /*Enable INT1 Interrupt Service Routine */

    while(1) //NEGATIVE ROTATIONS ARE CW. POSITIVE ROTATIONS ARE CCW
    {   

        T1= ((long)NR*10000)+(long)counter;
        T2= ((long)NRone*10000)+(long)counterone;

    }
    return 0;
}

void __attribute__((__interrupt__)) _INT0Interrupt(void);
void __attribute__((__interrupt__, auto_psv)) _INT0Interrupt(void)
{   
    if(InterruptFlag0_A==1) {
        if(Encoder0_B==1) {
            counter=counter-1;
            InterruptFlag0_A=0;
        } else if (Encoder0_B==0) {
            counter=counter+1;
            InterruptFlag0_A=0;
        }
    }
    if(counter==10000) {
        counter=0;
        NR=NR+1;
    } else if(counter==-10000) {
        counter=0;
        NR=NR-1;
    }
}

void __attribute__((__interrupt__)) _INT1Interrupt(void);
void __attribute__((__interrupt__, auto_psv)) _INT1Interrupt(void)
{   
    if(InterruptFlag1_A==1) {
        if(Encoder1_B==1) {
            counterone=counterone+1;
            InterruptFlag1_A=0;
        } else if (Encoder1_B==0) {
            counterone=counterone-1;
            InterruptFlag1_A=0;
        }
    }
    if(counterone==10000) {
        counterone=0;
        NRone=NRone+1;
    } else if(counterone==-10000) {
        counterone=0;
        NRone=NRone-1;
    }
}

Gracias

    
pregunta Raz

2 respuestas

3

Nunca conecte entradas externas como esta directamente a los pines de interrupción. Los pines de interrupción se deben usar con entradas "seguras" que no pueden escapar y dejan al controlador un charco de goteo de lodo cuando trata valientemente de dar servicio a interrupciones sin fin.

(en realidad no matará a la MCU, pero su aplicación integrada simplemente no funcionará)

Para cosas como los codificadores, es mejor usar el hardware del contador y luego tener una interrupción periódica para ver los conteos y determinar cuántos conteos por intervalo de tiempo está viendo, lo que luego le dirá qué tan rápido está girando el motor. Si también necesita información direccional, puede ejecutar las salidas del codificador I / Q a las entradas de reloj / dirección de los IC de contador arriba / abajo estándar y luego encuestarlos con el microcontrolador.

Sé que probablemente este no sea el tipo de respuesta que esperabas, pero usar interrupciones para contar los pulsos del codificador es un mal diseño.

    
respondido por el akohlsmith
0

Creo que para este diseño sería mejor utilizar el periférico de captura de entrada en su microcontrolador en lugar de interrupciones externas. Brevemente, el periférico de captura de entrada funciona junto con un temporizador para programar eventos externos. Puede conectar un canal de codificador a cada canal de captura de entrada (dos codificadores en cuadratura = 4 líneas totales y, afortunadamente, el 4011 que está usando tiene cuatro líneas de captura de entrada). El periférico de captura de entrada se puede configurar para desencadenar una variedad de condiciones que incluyen:

  • Cada flanco ascendente en la señal
  • Cada borde que cae
  • Cada cuarto borde ascendente
  • Cada decimosexto borde ascendente
  • Cada borde ascendente y descendente

(Esto proviene de la hoja de datos de su chip, pg78)

Cuando se produce una condición de activación, el periférico lee el valor actual de un temporizador que especifique (creo que ya sea Timer 2 o Timer 3 para su chip). Almacena ese valor en un FIFO que tiene cuatro palabras de 16 bits de profundidad. También puede generar una interrupción, o puede ver el FIFO y ver cuándo se llena. Posiblemente puede causar una interrupción cuando la FIFO también está llena, no lo he comprobado.

La aplicación de esto a un codificador de cuadratura sería utilizar dos canales de captura de entrada con el periférico utilizando un temporizador con una frecuencia adecuada. Probablemente configure ambos canales para utilizar una condición de flanco ascendente, o posiblemente cada 4o o 16o flanco ascendente. La elección de estos depende del nivel de precisión que necesite, la frecuencia del temporizador y las velocidades que intentará medir. Hay muchos factores con los que puedes jugar para obtener una mejor precisión de este sistema. Para este ejemplo, la diferencia entre dos bordes ascendentes en un canal será proporcional a la velocidad, y la diferencia entre los bordes ascendentes de un canal a otro le dirá en qué dirección está girando el motor.

Si puede ahorrar un temporizador y el periférico de captura de entrada, esta es la mejor manera de conectar dos codificadores.

    
respondido por el AngryEE

Lea otras preguntas en las etiquetas