Hi
Vorweg: Das reine Mitzählen klappt.
Drehencoder, eBay (360/600 /r erhältlich)
Laut WWW sollte man mit der Versorgungsspannung nicht wirklich über 7V hinaus gehen, da dann der enthaltene 7805 wohl zu warm wird, kleiner 7V wären ungünstig, da dort der 7805 nicht arbeitet.
Das Signal zeigt aber keinerlei Änderung zwischen 18V und 3,5V (die 18 waren irrtümlich ... krumme Finger und so) - unter 3,5V versagt die interne Elektronik - die Ausgangs-Signale gehen Beide durch die PullUPs auf HIGH..
Der derzeitige Sketch entstammt Diesem hier:
Quelle:Re: Rotary Encoder, Jurs, #11
Auf dem Beispiel ist Alles rausgeflogen, was mit mehr als einem Encoder zu tun hat, sämtliche FORs, auch zählt meine ISR jetzt die absoluten Impulse, statt relativ.
Mein aktueller Encoder liefert 600 Perioden pro Umdrehung, macht 2400 Impulse.
Angestrebte Geschwindigkeit 1500r/min (Spindel Drehbank), sind 25 die Sekunde, macht 60kHz.
Lange Rede, kurzer Sinn:
Bei meinen Versuchen (die letzten drei Tage) hatte ich gerade bei höheren Drehzahlen immer wieder Fehler, also Sprünge in den Encoder-Mustern.
Die konnte ich heute ausmerzen - hatte mir die Signale am Oszi angeschaut - vll. sind die Signale ja nicht 90° versetzt, sondern nur 50°?? Dann hätte ich natürlich zwei Mal eine wesentlich kürzere Zeit zwischen den Impulsen, was die Fehl-Zählungen erklären würde. Die Lösung war aber viel primitiver - kleinerer PullUP (2k2, meine Brot-und-Butter-Widerstände, Rollenware) und der Hase rennt.
Die Impulse sind super sauber 90° auseinander.
Auch habe ich in der ISR D13 toggeln lassen ... bei angestrebten 125kHz messe ich 156kHz, das Signal ist aber sehr verwaschen - hier wollte ich eigentlich nur sichergehen, daß ich halbwegs richtig gerechnet habe und der Timer auch macht, was ich denke, daß Er macht - Er macht!
Momentane Tests per Akkuschrauber, Der - laut Aufdruck - ebenfalls 1500r/min im hohen Gang haben soll (1556 durch Arduino gemessen).
In der ISR werden nur die Encoder-Muster vorher<>jetzt verglichen, nur wenn ungleich, wird weiter geprüft.
- Beide werden zusammen kopiert/geschoben
- die 4 Fälle für + bzw. die 4 Fälle für - in switch abgefragt
- als default einen Error-Counter hochzählen
Mit kleineren PullUPs bleibt der Error-Count derzeit auf 0.
Maximal erreichte Geschwindigkeit 62250 Impulse/Sekunde (25,9r/Sek - 1556r/Min) - ohne Error.
//Quelle des Original: https://forum.arduino.cc/index.php?topic=318170.msg2202599#msg2202599
// rotary encoder demo by 'jurs' for Arduino Forum
// This is the code for the main "sketch"
#include "encoder.h"
#define BAUDRATE 115200L // serial baud rate
int32_t diff; //Platz für die Differenz des Zählerwert binnen einer Sekunde
void setup() {
Serial.begin(BAUDRATE);
Serial.println();
Serial.println("Good night and good luck!"); // print some Test-Message at beginning
beginEncoders();
pinMode(13, OUTPUT);
}
void printEncoders()
{ // print current count of each encoder to Serial
Serial.print(stepsave);
Serial.print('\t');
Serial.print(error);
Serial.print('\t');
Serial.print(diff);
Serial.println();
}
void loop() {
if (updateEncoders()) printEncoders();
static int32_t stepold = 0; //Die aktuelle Geschwindigkeit (Steps pro Sekunde)
static uint32_t oldmillis;
if (millis() - oldmillis >= 1000) {
oldmillis += 1000;
diff = stepsave - stepold;
stepold = stepsave;
}
}
Die encoder.h :
// rotary encoder include file by 'jurs' for Arduino Forum
// This is the code for a new "Tab" within the sketch with Tab name "encoder.h"
#include <Arduino.h>
volatile boolean tic=false; //wird auf TRUE gesetzt, wenn im Timer-ISR der Wert geändert wurde
volatile int32_t error; //wird bei übersprungenen Mustern hochgezählt
volatile int32_t steps; //ISR-Variable
int32_t stepsave; //Variable für im Sketch
void startTimer2() // start TIMER2 interrupts
{
noInterrupts();
// Timer 2 CTC mode
/* Teiler CS22_CS21_CS20
000 STOP
001 :1 -> 16MHz
010 :8 -> 2MHz
011 :32 -> 500kHz
100 :64 -> 250kHz
101 :128 -> 125kHz
110 :256 -> 62.5kHz
111 :1024 -> 15.625kHz
*/
TCCR2B = (1<<CS21) | (1<<CS20); //Teiler 32 - im Original wird WGM22 auch gesetzt
TCCR2A = (1 << WGM21); //CTC //WGM22 ist aber 'Reserved' ... ?? Geht auch Ohne ...
//OCR2A = 1; //alle 2 Counter -> ISR 250kHz
//OCR2A = 2; //T32, OCR2A=2, Verzählt sich trotz 166kHz Abtastrate (156kHz gemessen)
//OCR2A = 5; //alle 6 Counter -> ISR 83.3kHz
//OCR2A = 6; //alle 7 Counter -> ISR 72.4kHz
//OCR2A = 7; //alle 8 Counter -> ISR 62.5kHz
//OCR2A = 9; //alle 10 Counter -> ISR 50kHz
//OCR2A = 19; //alle 20 Counter -> ISR 25kHz
OCR2A=2;
TIMSK2 = (1 << OCIE2A); // enable Timer 2 interrupts
interrupts();
}
void beginEncoders()
{ // active internal pullup resistors on each encoder pin and start timer2
pinMode(2, INPUT);
pinMode(3, INPUT);
startTimer2();
}
boolean updateEncoders()
{ // read all the 'volatile' ISR variables and copy them into normal variables
boolean changeState = false;
if (tic){
do{
tic=false;
stepsave=steps;
}while(tic==true); //wenn in der do-while die ISR zugeschlagen hat
changeState = true; //dann halt erneut auslesen
}
return changeState;
}
ISR(TIMER2_COMPA_vect) // handling of TIMER2 interrupts
{
static byte oldp=0; //Merker des alten Zustand
byte newp=(PIND>>2)&0x3; //neuen Zustand einlesen - D2 und D3
if (oldp!=newp){ //nur bei Änderung weiter Prüfen
tic=true; //Änderung nach Außen sichtbar machen
oldp|=newp<<2; //oldp als Temp-Variable missbrauchen
switch (oldp){
case 0b0100: //von Muster 00 -> 01
case 0b1101: // 01 -> 11
case 0b1011: // 11 -> 10
case 0b0010:steps++;break; // 10 -> 00
case 0b0001:
case 0b0111:
case 0b1110:
case 0b1000:steps--;break;
default:error++; // wenn die Alle nicht gepasst haben - Problem
}
oldp=newp; //neuen Wert übernehmen
}
}
Vll kann ja Wer Was damit anfangen - frühe Alpha ![]()
MfG
Edit
OCR2A=2 -> 166kHz, nicht wie zuvor im Kommentar stehend 125kHz (0-2 sind 3 Steps, somit bei Teiler 32 = 500kHz durch 3 -> 166kHz)
