Ich habe mit ein paar Servomotoren gespielt, die ich aus einem Überschuss an Bestückungsautomaten bekommen habe. Bisher habe ich ihre Pinbelegung dekodiert und arbeite daran, den Encoder zu lesen, hier kommt das Problem:
Nach dem, was ich beobachtet habe, ist der Motor mit 4096 Kuadraturimpulsen pro Umdrehung + 1 Indeximpuls pro Umdrehung ausgestattet. Einige Tests in der Arduino IDE haben gezeigt, dass der Motor etwas schneller dreht und der Encoder anfängt, Schritte zu verlieren ...
Ich habe mich entschieden, den Code auf AS7 zu migrieren und den gesamten Arduino-Overhead zu spülen, aber der Chip scheint nicht in der Lage zu sein, damit umzugehen. Korrigiert mich, wenn ich bei folgendem falsch liege:
Mit 2048 cpr (nur mit dem ansteigenden Impuls eines Cuadraturkanals) und einer Drehzahl von 3000 U / min ist eine Umdrehung in 0,02 Sekunden abgeschlossen.
Unter der Annahme der vorherigen 20 ms / 2048 ppr haben wir alle 0,097 ms eine ansteigende Flanke -> 97 uS geben oder nehmen.
Reicht diese Zeit, um die folgende ISR auszuführen?:
#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);
}
Wenn nicht, wie soll ich es tun ... Dedizierter Zähler-IC?
Danke
**Bearbeiten:** Aufnahme des Logikanalysators, der eine Umdrehung (Index) mit Encoder A vergleicht
avr-gcc
Ich habe Ihren Code mit Optimierung durchlaufen -Os
(YMMV, wenn Sie einen anderen Compiler, Flags usw. verwenden, aber in könnte ein guter Ausgangspunkt sein) und das Ergebnis zerlegt, hier ist es:
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
Zahlen vor Befehlsadressen sind meine Ergänzung zur Disassembler-Ausgabe, Anzahl der Zyklen für die Ausführung basierend auf dem AVR-Befehlssatzhandbuch . Wenn ich es richtig zähle, sind es insgesamt 43 Zyklen + 5 Zyklen für die Interrupt-Antwort (+ etwa 3 Zyklen für die Ausbreitung des Pin-Wechsels). Der ISR-Code kann bei Bedarf manuell viel kürzer optimiert werden. Aber es sind immer noch etwa 50 Zyklen, 3 us bei 16 MHz.
PIND wird 12 Zyklen nach ISR-Start gelesen, etwa 20 Zyklen (1,25 us) nach INT0-Flanke. Sollte noch ok sein.
Sie müssen nicht viel Rand, aber es sollte funktionieren. OTOH jeder andere ISR wird ihn wahrscheinlich "töten", da ATmega keinen Interrupt-Controller mit Prioritätsbehandlung hat. Übrigens. In dem Code, den Sie hier einfügen, gibt es keine Verarbeitung von count
Variablen, daher muss es selbst zum Testen komplizierter sein. Sind Sie sicher, dass Sie dort nichts tun, was die ISR-Latenz beeinflusst?
Als alternative Lösung – wenn Sie XMega für Ihr Projekt in Betracht ziehen können (vorausgesetzt, Sie möchten AVR verwenden), haben diese Hardware-Unterstützung für Encoder und Sie können damit ohne FW-Interaktion gegensteuern.
count
Variable liest, während ISR sie in der Mitte aktualisieren kann. Wenn Sie einen Off-by-One-Fehler sehen, kann dies möglicherweise durch die Latenz der Erkennung der gesamten Umdrehung im Code verursacht werden.Zwischen ansteigenden Flanken liegen weniger als 5 us, da zwei Sensoren vorhanden sind. Dadurch bleibt keine CPU-Zeit übrig, um die Informationen tatsächlich für irgendetwas zu verwenden. Außerdem tasten die meisten sauberen Quadratur-Decoder-Schemata zwischen allen 4 Kanten ab, sodass nur 2,5 uS zwischen Kanten/Abtastungen verbleiben würden.
Sie werden wahrscheinlich sehr knapp bei der Zeit sein, um 100% in der Firmware zu erledigen.
10us ist selbst für schnellere Taktraten ziemlich schnell.
Möglicherweise möchten Sie den Taktimpuls in einen Timer / Zähler einspeisen und diesen als Vorskalar verwenden, wenn Sie den Motor mit Geschwindigkeiten antreiben. Natürlich ist der Übergang von einem Modus zum anderen schwierig und muss bei langsameren Geschwindigkeiten erfolgen, bei denen Sie ein ausreichend breites Zeitfenster zwischen den Impulsen garantieren können, um den Wechsel durchzuführen.
Martin
Martin
Asmyldof
Alex
Alex
Chris Stratton
int
hat 16 Bit, sodass der Zugriff normalerweise in zwei Schritten erfolgt. Schließlich scheint es eine schlechte Idee zu sein, ein Pick & Place für Experimenter-Teile zu verschrotten - es ist wahrscheinlich mehr wert als Plattform für jemanden, der mit einem Pick & Place spielen möchte, oder als Teile für die Wartung eines vergleichbaren Modells.Scott Seidmann