He estado jugando con un par de servomotores que obtuve de un excedente de máquinas de recoger y colocar. Hasta ahora, he decodificado su pinout y estoy trabajando para leer el codificador, aquí viene el problema:
Por lo que observé, el motor viene equipado con una cuadratura de 4096 pulsos por revolución +1 pulso índice por revolución. Haciendo algunas pruebas en el IDE de Arduino mostró que girando el motor un poco más rápido y el codificador comienza a perder pasos...
Decidí migrar el código a AS7 y descargar toda la sobrecarga de Arduino, pero el chip parece incapaz de manejarlo. Corrígeme si me equivoco en lo siguiente:
Con 2048 cpr (solo usando el pulso ascendente de un canal de cuadratura) y una velocidad de rotación de 3000 rpm, se completa una revolución en 0,02 segundos.
Asumiendo los 20mS / 2048ppr anteriores, tenemos un flanco ascendente cada 0.097mS -> 97uS más o menos.
¿Es ese tiempo suficiente para ejecutar el siguiente ISR?:
#define F_CPU 16000000UL
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <stdio.h>
volatile int count;
int main(void)
{
DDRD = (0<<PORTD2) | (0<<PORTD3)| (0<<PORTD4);
PORTD = (0<<PORTD2) | (0<<PORTD3)| (0<<PORTD4);
EICRA = (1 << ISC11) | (1 << ISC01); // Configure interrupt trigger on rising edge of INT0
EIMSK = (1 << INT0); //ebable INT0
sei();
while (1)
{
}
}
ISR (INT0_vect){
uint8_t i = ((PIND & 0b00010000)>>4);
if (i == 1) {
count = count +1;
}else{
count = count -1;
}
EIFR = (1<<INTF0);
}
Si no, ¿cómo debo hacerlo... Contador IC dedicado?
Gracias
**Editar:**captura del analizador lógico comparando una revolución (índice) con el codificador A
He ejecutado su código avr-gcc
con -Os
optimización (YMMV si usa un compilador diferente, banderas, etc., pero podría ser un buen punto de partida) y desarmé el resultado, aquí está:
00000090 <__vector_1>:
2 90: 1f 92 push r1
2 92: 0f 92 push r0
1 94: 0f b6 in r0, 0x3f ; 63
2 96: 0f 92 push r0
1 98: 11 24 eor r1, r1
2 9a: 8f 93 push r24
2 9c: 9f 93 push r25
1 2 9e: 4c 9b sbis 0x09, 4 ; 9
2 . a0: 06 c0 rjmp .+12 ; 0xae <__vector_1+0x1e>
. 2 a2: 80 91 00 01 lds r24, 0x0100
. 2 a6: 90 91 01 01 lds r25, 0x0101
. 2 aa: 01 96 adiw r24, 0x01 ; 1
. 2 ac: 05 c0 rjmp .+10 ; 0xb8 <__vector_1+0x28>
2 . ae: 80 91 00 01 lds r24, 0x0100
2 . b2: 90 91 01 01 lds r25, 0x0101
2 . b6: 01 97 sbiw r24, 0x01 ; 1
2 b8: 90 93 01 01 sts 0x0101, r25
2 bc: 80 93 00 01 sts 0x0100, r24
1 c0: 81 e0 ldi r24, 0x01 ; 1
1 c2: 8c bb out 0x1c, r24 ; 28
2 c4: 9f 91 pop r25
2 c6: 8f 91 pop r24
2 c8: 0f 90 pop r0
1 ca: 0f be out 0x3f, r0 ; 63
2 cc: 0f 90 pop r0
2 ce: 1f 90 pop r1
4 d0: 18 95 reti
Los números antes de las direcciones de instrucción son mi adición a la salida del desensamblador, el número de ciclos para la ejecución basado en el Manual del conjunto de instrucciones AVR . Si lo estoy contando correctamente, son 43 ciclos en total + 5 ciclos para la respuesta de interrupción (+ aproximadamente 3 ciclos para que se propague el cambio de pin). El código ISR se puede optimizar a mano en mucho más corto si es necesario. Pero aun así son unos 50 ciclos, 3 us @ 16 MHz.
PIND se lee 12 ciclos después del inicio de ISR, aproximadamente 20 ciclos (1,25 us) después del flanco INT0. Debería estar bien.
No tienes mucho marginal, pero debería funcionar. OTOH, cualquier otro ISR probablemente lo "matará", ya que ATmega no tiene un controlador de interrupción con manejo de prioridad. Por cierto. en el código que pone aquí, no hay procesamiento de count
variables, por lo que incluso para la prueba debe ser más complicado. ¿Está seguro de que no está haciendo nada que afecte la latencia de ISR allí?
Como una solución alternativa, si puede considerar XMega para su proyecto (asumiendo que desea usar AVR), estos tienen soporte de hardware para el codificador y puede manejarlo sin necesidad de interacción FW.
count
mientras que ISR puede actualizarla en el medio. Si ve un error de apagado por uno, entonces, tal vez, puede ser causado por la latencia de la detección de revolución completa en el código.Habrá menos de 5 usec entre flancos ascendentes porque hay dos sensores. Eso dejará cero tiempo de CPU para usar la información para cualquier cosa. Además, la mayoría de los esquemas de decodificadores de cuadratura limpios muestrean entre los 4 bordes, por lo que dejaría solo 2,5 uS entre bordes/muestras.
Probablemente tendrá muy poco tiempo para hacer el 100% en el firmware.
10us es bastante rápido incluso para velocidades de reloj más rápidas.
Es posible que desee considerar alimentar el pulso del reloj en un temporizador/contador y usarlo como un preescalar cuando se conduce el motor a velocidades. Por supuesto, la transición de un modo a otro es complicada y debe realizarse a velocidades más lentas donde pueda garantizar una ventana de tiempo lo suficientemente amplia entre pulsos para realizar el cambio.
Martín
Martín
Asmyldof
aleix
aleix
chris stratton
int
es de 16 bits, por lo que el acceso normalmente sería en dos pasos. Por último, descartar un pick & place para las piezas del experimentador parece una mala idea; probablemente valga más la pena como plataforma para alguien que quiere jugar con un pick & place, o como piezas para mantener un modelo comparable.scott seidman