Forum: Mikrocontroller und Digitale Elektronik Linear Encoder (Inkremental) 40.000 Inkremente/Sec + Raspberry Pi?


von Niko U. (Gast)


Lesenswert?

Guten Abend allerseits :)

Ich bin zurzeit dabei, folgenden Encoder via Raspberry Pi [B+] 
auszulesen:

https://www.siko-global.com/adbimage/1713/asset_original/datenblatt-msk2000.pdf 
(Datenblatt Siko MSK2000)

Dieser hat folgende Auflösung: 0,25 mm.

Das Ziel ist, dass ich durch den Encoder die aktuelle Position erfahre 
(bei senkrechter Bewegung). Der Encoder wird mit einer maximalen 
Geschwindigkeit von 10 m/s verfahren, das ergibt:

40.000 Pulse/Sekunde (wenn man die volle Auflösung betrachtet).

Die erste Hürde konnte ich bereits durch Hilfe in diesem Forum 
bewältigen. Der Encoder stellt 4 Signalleitungen bereit, wovon 2 die 
invertierten Signale darstellen (RS422 Standard). Das ganze wird von 
einem RS422 Receiver IC ausgewertet, welcher dem Raspberry Pi TTL 
Signale zur Verfügung stellt. Funktioniert soweit einwandfrei (überprüft 
mit dem Ossi).

Nun fehlt noch die softwareseitige Auswertung der Signale, und da kommt 
die Hauptfrage ins Spiel:

Kann der raspberry pi mit einer solchen Auflösung umgehen? In einem 
initialen Testprogramm kam ich beim senkrechten Verfahren nicht wieder 
auf den Ausgangswert zurück, sprich es gehen Signale verloren. Das erste 
Programm wurde mit der wiringPi Bibliothek umgesetzt. Hier der 
Programmcode:
1
#include "encoder_raspi.h"
2
#include <wiringPi.h>
3
#include <stdio.h>
4
#include <stdlib.h>
5
6
struct Encoder_t {
7
    uint8_T Num;
8
    uint8_T PinA;
9
    uint8_T PinB;
10
    int32_T Position;
11
    uint8_T LastReading;
12
    struct Encoder_t *Next;
13
};
14
15
typedef struct Encoder_t Encoder; 
16
Encoder *encList = NULL;
17
18
static int32_T EncLookup[16] = 
19
{
20
    0, // 0b0000
21
   -1, // 0b0001
22
   +1, // 0b0010
23
    0, // 0b0011
24
   +1, // 0b0100
25
    0, // 0b0101
26
    0, // 0b0110
27
   -1, // 0b0111
28
   -1, // 0b1000
29
    0, // 0b1001
30
    0, // 0b1010
31
   +1, // 0b1011
32
    0, // 0b1100
33
   +1, // 0b1101
34
   -1, // 0b1110
35
    0, // 0b1111
36
};
37
38
// Encoder interrupt service routine
39
static void encoderISR(void)
40
{
41
    int state, reading;
42
    Encoder *enc;
43
    
44
    // Update encoder positions
45
    for (enc = encList; enc != NULL; enc = enc->Next) {
46
        reading = digitalRead(enc->PinB) | (digitalRead(enc->PinA) << 1);
47
        state = (enc->LastReading << 2) | reading;
48
        enc->Position += EncLookup[state];
49
        enc->LastReading = reading;
50
    }
51
}
52
53
// Function used to lookup encoder object based on encoder number
54
static Encoder *lookupEncoder(uint8_T num)
55
{
56
    Encoder *enc;
57
    
58
    // Remove encoder from linked list and de-allocate storage
59
    enc = encList;
60
    while ((enc != NULL) && (enc->Num != num)) {
61
        enc = enc->Next;
62
    }
63
64
    return enc;
65
}
66
67
// Encoder initialization 
68
void encoderInit(uint8_T num, uint8_T pinA, uint8_T pinB)
69
{
70
    Encoder *newEnc;
71
    static int wiringPiInitialized = 0;
72
    
73
    // Initialize wiringPi if not done already
74
    if (!wiringPiInitialized) {
75
        wiringPiSetupGpio(); // Use Broadcom GPIO pin numbers
76
        wiringPiInitialized = 1;
77
    }
78
    
79
    // Create a new encoder
80
    newEnc = (Encoder *)malloc(sizeof(Encoder));
81
    if (newEnc == NULL) {
82
        perror("encoderInit/Memory allocation error");
83
        exit(-1);
84
    }
85
    
86
    // Initialize encoder parameters
87
    newEnc->Num         = num;
88
    newEnc->PinA        = pinA;
89
    newEnc->PinB        = pinB;
90
    newEnc->Position    = 0;
91
    newEnc->LastReading = 0;
92
    newEnc->Next        = NULL;
93
    
94
    // Install ISR service routine that will update encoder position
95
    pinMode(newEnc->PinA, INPUT);
96
    pinMode(newEnc->PinB, INPUT);
97
    // Disable pull-ups
98
    pullUpDnControl(newEnc->PinA, PUD_OFF);
99
    pullUpDnControl(newEnc->PinB, PUD_OFF);
100
    wiringPiISR(newEnc->PinA, INT_EDGE_BOTH, &encoderISR);
101
    wiringPiISR(newEnc->PinB, INT_EDGE_BOTH, &encoderISR);
102
    newEnc->LastReading = digitalRead(newEnc->PinB) | (digitalRead(newEnc->PinA) << 1);
103
    
104
    // Add to encoder list
105
    if (encList == NULL) {
106
        encList = newEnc;
107
    }
108
    else {
109
        Encoder *enc = encList;
110
        while(enc->Next != NULL) {
111
            enc = enc->Next;
112
        }
113
        enc->Next = newEnc;
114
    }
115
}
116
117
// Returns encoder position
118
int32_T encoderOutput(uint8_T num)
119
{
120
    Encoder *enc;
121
    
122
    enc = lookupEncoder(num);
123
    
124
    return (enc->Position);
125
}
126
127
// Terminate encoder
128
void encoderTerminate(uint8_T num)
129
{
130
    Encoder *enc, *prevEnc;
131
    
132
    if (encList == NULL) {
133
        return;
134
    }
135
    
136
    // Remove encoder from linked list and de-allocate storage
137
    enc = encList;
138
    while ((enc != NULL) && (enc->Num != num)) {
139
        prevEnc = enc;
140
        enc = enc->Next;
141
    }
142
    if (enc == NULL) {
143
        return;
144
    }
145
    
146
    // Remove encoder from list
147
    prevEnc->Next = enc->Next;
148
    free(enc);
149
}
150
// [EOF]

Ich könnte mir vorstellen, dass man bessere Programmlaufzeiten erreicht, 
wenn man auf die wiringPi Bibliothek verzichtet. Alternativ habe ich von 
der pigpio Bibliothek gelesen, welche wohl etwas schneller sein soll. 
Hier werden aber auch lediglich ca. 8000 Interrupts/s als machbar 
angegeben. Wenn ich richtig gerechnet habe, wären es in meinem Fall 
40.000 Interrupts/sekunde...

Was würdet ihr empfehlen? Meine Gedanken sind:
- pigpio Bibliothek testen
- Encoder mit einem Arduino separat auslesen
- einen IC verwenden, welcher den Encoder auswertet (habe damit noch 
keine Erfahrung, bin aber mehrmals drüber gestolpert beim recherchieren)

Mein Wunsch wäre dabei natürlich beim Raspberry Pi bleiben zu können. 
Dieser liest aktuell bereits zwei weitere Sensoren via SPI Bus aus 
(deswegen auch meine Befürchtung, dass der Encoder zusätzlich zuviel 
Last sein könnte).

Viele Grüße,

Niko

von Olaf (Gast)


Lesenswert?

> Wenn ich richtig gerechnet habe, wären es in meinem Fall
> 40.000 Interrupts/sekunde...

Du brauchst mehr wie 4x40000 Timerinterrupts pro Sekunde. Und die 
zuverlaessig. Viel Glueck. :-)

> - einen IC verwenden, welcher den Encoder auswertet (habe damit noch
> keine Erfahrung, bin aber mehrmals drüber gestolpert beim recherchieren)

Das waere eine Moeglichkeit. Eine andere waere es einen Microcontroller 
zu verwenden der bereits die passende Hardware integriert hat. Oder sich 
ein kleines CPLD zu programmieren.

> Mein Wunsch wäre dabei natürlich beim Raspberry Pi bleiben zu können.

Fuer hardwarenahe und vollem timingkritische Sachen ist das Dingen eher 
ungeeignet.

Olaf

von Wolfgang (Gast)


Lesenswert?

Olaf schrieb:
>> Wenn ich richtig gerechnet habe, wären es in meinem Fall
>> 40.000 Interrupts/sekunde...
>
> Du brauchst mehr wie 4x40000 Timerinterrupts pro Sekunde. Und die
> zuverlaessig. Viel Glueck. :-)

Ack

Niko U. schrieb:
> Kann der raspberry pi mit einer solchen Auflösung umgehen?

Warum nimmst du nicht einen Arduino mit ARM Controller. Der kann das mit 
seinem Timer/Counter per Hardware erledigen.

von Peter II (Gast)


Lesenswert?

Olaf schrieb:
>> Mein Wunsch wäre dabei natürlich beim Raspberry Pi bleiben zu können.
>
> Fuer hardwarenahe und vollem timingkritische Sachen ist das Dingen eher
> ungeeignet.

naja, am Raspi selber liegt es aber nicht. Man könnte ihn auch ohne 
Linux betreiben, dann schafft er es auch ohne Probleme.

http://www.valvers.com/open-software/raspberry-pi/step01-bare-metal-programming-in-cpt1/

von Joe F. (easylife)


Lesenswert?

Ich würde dir ebenfalls zu einem CPLD raten.
Decodierung (Richtung / Counts) im CPLD in einen 16-bit breiten Counter.

Dann reicht es dir diesen Counter (z.B. per SPI) im Extremfall nur 1x 
pro Sekunde auszulesen, und trotzdem verpasst du keinen einzigen Count 
oder Überlauf.

: Bearbeitet durch User
von Joe F. (easylife)


Lesenswert?


von aSma>> (Gast)


Lesenswert?

Niko U. schrieb:
> Das Ziel ist, dass ich durch den Encoder die aktuelle Position erfahre
> (bei senkrechter Bewegung). Der Encoder wird mit einer maximalen
> Geschwindigkeit von 10 m/s verfahren, das ergibt:

Servus,
ein µC ist für Echtzeit besser geeignet. Als Beispiel, wie auch schon 
öffters genannt: stm32f103c8 mini board. Kostet lächerliche 2€. Plus 
vielleicht noch ein ST Link V2 Clone. Dort hast du 4 Timer, sodass du 4 
Encoder anschließen kannst. Für Arduino Sekte gibt es das: mini maple 
clone.

Stelle dir vor die Beere hängt für 0,5 s irgendwo fest, dann bist du 
schon 5m weiter. Vergiss das ganz schnell mal.

Nehme die Beere für Lan-Übertragung, Bildschirmausgabe, was weiß ich 
noch aber für eine schnelle Regelung sollte es schon ein µC sein.

Ein kleines Problem ist der 16 bit Timer. Aber mit ein paar Zeilen Code 
kann man alles locker zurecht biegen. Oder man nimmt einen Controller 
mit 32bit Timer.

Ich bin mit den stm32f103c8 sehr zufrieden. Damit konnte ich bisjetzt 
alles ohne irgendwelche Auslastung regeln.

mfg

von Sebastian S. (amateur)


Lesenswert?

@ aSma>>
Irgendwie läuft Dein Vorschlag auf einen "Eigenbau" des vorher 
vorgeschlagenen LFLS7166-S hinaus.

Stimmt, das Teil kostet ganz schön ziemlich und die Beschaffung wird 
wohl nicht ganz ohne sein. Aber nachdem Du Deinen Liebling aufgebaut, 
angepasst und programmiert hast, wirst Du es wohl bereuen diesen 
Vorschlag gemacht zu haben, weil Joe F's Lösung bereits läuft.

Sollte es aber um das Basteln um des Bastelns willen gehen, könnte ich 
mich mit deinem Ansatz anfreunden.

Als reinen Quadraturdekoder würde aber auch ein 08/15 µP reichen. 
Vorausgesetzt, er hat sonst nichts zu tun.

von aSma>> (Gast)


Lesenswert?

@ Sebastian S. (amateur)

Lasse dir erstmal die Zahlen durchgehen:
> Der Encoder wird mit einer maximalen
> Geschwindigkeit von 10 m/s verfahren ...

Wenn du immer noch der Meinung bist, dass es mit der Beere geht, dann 
viel Spaß. Vorher musst du den Linux Kernel raushauen und selber was 
zusammen programmieren. Oder man müsste sich reinlesen und einen 
Echtzeitkernen erstellen. Vielleicht geht es dann bei langsamer 
Geschwindigkeit.

Auch als Beispiel eingeführt ist Linux CNC mit der Beere. Läuft auch 
perfekt allerdings mit einen Pic µC, der die Echtzeit Ausgabe übernimmt.

> Stimmt, das Teil kostet ganz schön ziemlich und die Beschaffung wird
> wohl nicht ganz ohne sein. Aber nachdem Du Deinen Liebling aufgebaut,
> angepasst und programmiert hast, wirst Du es wohl bereuen diesen
> Vorschlag gemacht zu haben, weil Joe F's Lösung bereits läuft.

Er kann sich das schon kaufen. Wird aber merken, dass es nicht so laufen 
wird wie gewünscht, wegen der Latenzzeit.

> Als reinen Quadraturdekoder würde aber auch ein 08/15 µP reichen.
> Vorausgesetzt, er hat sonst nichts zu tun.

Wozu diesen Stress? Ich würde auf einen µC mit Encoder Interface setzen. 
Darauf soll die Regelung laufen + Bus-Kommunikation mit der Beere. Dann 
braucht man sich nicht die Beine zu brechen bei einer Multiplikation.

mfg

von Sebastian S. (amateur)


Lesenswert?

Das mit dem 08/15 µP war wörtlich gemeint.

Ein ATTiny mit 20MHz hat, so nichts anderes zu tun ist, 20000000/40000 = 
500 Taktzyklen pro Dings. Das reich lange, um einen Zähler zu 
aktualisieren.
Ein paar Abfragen, wie's denn steht, sollten wohl auch noch zu 
beantworten sein.
Auch eine Abfrage, ob eine vorher angegebene Position (Zählerstand) 
erreicht ist, bzw. das setzen eines Pins, sollten problemlos machbar 
sein.

Würde mich nicht wundern, wenn in solchen Chips nicht auch was Ähnliches 
ist, nur mit anderem Etikett.

von Peter P. (peter_p781)


Lesenswert?

Interrupts in Kernel Mode laufen lassen.

von Georg (Gast)


Lesenswert?

Sebastian S. schrieb:
> Würde mich nicht wundern, wenn in solchen Chips nicht auch was Ähnliches
> ist, nur mit anderem Etikett.

Eher ein CPLD oder FPGA, das ist besser geeignet, man braucht ja nur 
einen 32bit-Zähler, und in Hardware kann der dann auch einige MHz 
zählen. Gute Werkzeugmaschinen mit 1 µ Auflösung und 10 m/s brauchen das 
leicht.

Georg

von Falk B. (falk)


Lesenswert?


von Niko U. (Gast)


Lesenswert?

wow... danke für das viele Feedback :) Damit hätte ich jetzt nicht 
gerechnet :)

Also vlt. etwas zum Hintergrund, warum ich den raspi nutze und nicht 
einen reinen uc:

Ich werte Beschleunigungsdaten in Matlab aus, der Encoder soll dabei als 
Positionsreferenz dienen. Da es für den Raspberry Pi offizielle 
Unterstützung seitens Matlab/Simulink gibt, ist die Wahl hierauf 
gefallen :) Zusätzlich nutze ich als Schnittstelle zum Pi einen Wifi USB 
Stick, was sich hier sehr einfach umsetzen ließ.
Die Auswertung der Beschleunigungssensoren läuft soweit (2 Stück, via 
SPI angebunden). Das ganze lässt sich dann in Simulink auswerten.

Mit den 10 m/s war ich wohl etwas übereifrig. Ich denke mal das wäre 
beim Verfahren per Hand auch schwer umzusetzen. Als Referenz sind wohl 
eher 1 m/s angedacht.

An ein Arduino Board habe ich auch schon gedacht, jedoch müsste ich dann 
die Anbindung an den vorhandenen Raspberry Pi umsetzen, da dieser ja mit 
Matlab /Simulink kommuniziert. Ich habe diesbezüglich aber auch schon 
Beispiele gesehen, die dass per SPI Bus lösen (und den nutze ich ja 
sowieso schon für die Beschleunigungssensoren). Wäre erstmal ein Ansatz 
:)

Von CPLDs habe ich noch nichts gehört :) Auf den ersten Blick hört sich 
das definitiv nach einer Lösung an, ich würde aber aus Zeitgründen 
lieber auf eine fertige Lösung zurückgreifen. Die Einarbeitung in diese 
Thematik würde mich jetzt zuviel Zeit kosten. Aber danke für den Tipp, 
merke ich mir mal für zukünftige Projekte :)

Auf Linux kann ich leider auch nicht verzichten, da dann die Einbindung 
in Matlab/Simulink nicht mehr funktionieren würde. Im Endeffekt wandelt 
Simulink das erzeugte Modell auch nur in C Code um, ich habe aber keinen 
Überblick, was bei der erstmaligen Einbindung des Raspberry Pis (bei der 
auch zeitgleich das Raspbian Image auf die SD Karte geschrieben wird) an 
Parametern auf dem Pi gesetzt wird.

Die fertigen ICs von USdigital habe ich auch schon entdeckt. Kennt 
jemand alternativen zu diesen, die man auch bei conrad o.ä. beziehen 
kann? Ich habe bei USdigital mal eine Anfrage gestellt, wie lange die 
Lieferung bei denen dauern würde (normalerweise dauert so etwas ja gerne 
mal einen Monat, dann brauche ich den IC auch nicht mehr :P).
Hab jetzt noch den LS7366R gefunden. Sehe jetzt auf die Schnelle nur das 
Eval Board mit dem LS7366R drauf, aber wäre ja auch ne Möglichkeit :)

@aSma
Du schlägst uC mit Encoder interface vor, schwebt dir da spontan etwas 
im Kopf rum? Das würde ja in die gleiche Richtung wie mit dem arduino 
board laufen (nur wäre mir jetzt neu, dass arduino boards ein encoder 
interface haben).


VG

Niko

von aSma>> (Gast)


Lesenswert?

Servus,
> Du schlägst uC mit Encoder interface vor, schwebt dir da spontan etwas
> im Kopf rum? Das würde ja in die gleiche Richtung wie mit dem arduino
> board laufen (nur wäre mir jetzt neu, dass arduino boards ein encoder
> interface haben).

Ich schrieb dazu schon was:
aSma>> schrieb:
> Autor: aSma>> (Gast)
> Datum: 21.05.2016 23:34

Stm32f103c8 mini board oder mini maple clone. Ich arbeite nicht mit 
arduino IDE, deshalb muss du dich selber schlau lesen. Zudem könnte man 
einen ST Link V2 Clone kaufen. Aber Arduino programmiert glaube ich über 
FTDI Chip...

Das Problem bei einen "Echtzeitkernel" ist die Latenzzeit. Bei 1m/s 
Verfahrgeschwindigkeit, so würde ich eine Abtastzeit von 1ms anstreben. 
Jetzt müsste man sich schlau lesen wie groß die Latenzen beim 
"Echtzeitkernel" liegen.

Du hast momentan ein normales Betriebssystem drauf, welches 
Ereignisgesteuert ist. Die Latenzen kann man nicht voraussagen. 
Angenommen während eines Versuches macht jemand den Browser auf oder 
eine email kommt an: Absturtz.

Versuchen mal Klug. Es gibt mehrere Wege nach Rom.

PS: suche auch nach "Quadrature Decoder chip 32 bit". Manchnal will man 
nur schnell an Ziel kommen.

von Joe F. (easylife)


Lesenswert?

Eine Alternative wäre noch der HCTL-2022
http://www.farnell.com/datasheets/1697797.pdf

Schnell verfügbar bei farnell bzw. hbe-shop.de

: Bearbeitet durch User
von Marco H. (damarco)


Lesenswert?

Warum das nicht funktioniert liegt einfach daran das es keine Interrupts 
im Userspace gibt.

Die WiringPi Lib macht vermutlich nichts anderes als den GPIO beim 
Treiber zu registrieren. So lange kein Interrupt auftritt wird der 
Thread schlafen gelegt.

Beim Auftreten des Ereignisses weckt ein Kernelthread den Userthread auf 
und kopiert die Daten in den Userspace.


So ganz direkt läuft das nicht ab. Erst prüft der Treiber ob die ISR auf 
ihn war dann beendet er die ISR und ruft den SoftIRQ auf. Diese Routine 
wird je nach Priorität ausgeführt wenn dort eine Funktion registriert 
ist.  Man kann aber dafür sorge das diese gleich nach dem ISR 
abgearbeitet wird. Das sorgt für zusätzliche Latenz. Jedenfalls irrend 
eine Funktion weckt den Userthread auf.


Das ganze funktioniert auch deswegen schlecht weil jedes mal der Thread 
schlafen und aufgeweckt werden muss und bevor der schläft neue Daten da 
sind. Die dann verloren sind, außerdem werden durch deinen ISR alle 
anderen gesperrt.

Das ganze ist schon möglich aber mit einen Kernel Treiber und ich glaube 
da fehlt dir etwas das Verständnis was im Kernel so alles abläuft ;)

Außerdem wird dein Code im Userspace so oft aufgerufen das er durch den 
schedule keine zeit erhält alle Ticks zu lesen.

Du merkst das funktioniert so nicht, da muss externe Hardware ran.

von Veit D. (devil-elec)


Lesenswert?

Hallo,

du solltest auch deine Encode Funktion schneller machen, denke ich.
Wie das geht, zeigt Peter D. hier
Beitrag "Drehgeber auslesen"
https://www.mikrocontroller.net/articles/Drehgeber

und 40.000 / Sekunde

Da hat der µC für einen Impuls 25µs Zeit.
Ein einfacher Atmel der sonst nichts weiter macht als das und das 
Ergebnis ausgibt schafft das. Ohne Interrupt, reines Polling. Mit 16MHz 
dauert 1 Takt 62,5ns.

von Wolfgang (Gast)


Lesenswert?

Niko U. schrieb:
> Das würde ja in die gleiche Richtung wie mit dem arduino
> board laufen (nur wäre mir jetzt neu, dass arduino boards ein encoder
> interface haben).

Dann hast du wieder was dazu gelernt. ;-)

Wolfgang schrieb:
> Warum nimmst du nicht einen Arduino mit ARM Controller.

von Marco H. (damarco)


Lesenswert?

Eben z.Bsp einen sam3x (Arduino DUE) der hat einen Quadrature Decoder 
mit drauf und kann sogar Hardwareseitig den Speed berechnen.

http://www.atmel.com/images/atmel-11057-32-bit-cortex-m3-microcontroller-sam3x-sam3a_datasheet.pdf

Die Frage ist aber wie oft er den Wert braucht. Denn sonst muss er 
weitere Funktionen auslagern. Z.Bsp Interrupt bei bestimmter Position 
etc.

Anbindung könnte recht einfach über USB Seriell erledigt werden. Es 
kommt darauf an was man mit dem Wert machen will.

: Bearbeitet durch User
von Zaehler (Gast)


Lesenswert?

Chip für das Zählen kaufen und per spi anbinden:

iC Haus iC-MD

https://www.ichaus.de/product/iC-MD

von Dennis H. (c-logic) Benutzerseite


Lesenswert?

Zaehler schrieb:
> Chip für das Zählen kaufen und per spi anbinden:
>
> iC Haus iC-MD
>
> https://www.ichaus.de/product/iC-MD

> Veit Devil:
> Da hat der µC für einen Impuls 25µs Zeit.
> Ein einfacher Atmel der sonst nichts weiter macht als das und das
> Ergebnis ausgibt schafft das. Ohne Interrupt, reines Polling. Mit 16MHz
> dauert 1 Takt 62,5ns.

Ich halte die Tiny-Lösung für sehr nützlich.
SPI dürfte für den Tiny,während er nichts anderes tut als den Impuls 
auszuwerten,dann auch kein Problem.
Nach Wahl mit Indeximpuls.
Nach Wahl mit Interruptpin für die SPI-Abfrage oder Dauerfeuer als Paket 
mit ChipSelect.
Der Tiny macht das sicherlich auch noch mit 4 Encodern Problemlos falls 
nötig.

: Bearbeitet durch User
von PittyJ (Gast)


Lesenswert?

Nimm für sowas immer einen eigenen Microcontroller. Die haben sowas in 
Hardware und kein Overhead durch ein Betriebssystem.

Bei einer Lösung habe ich auch einfach einen Arduino über USB an den 
Raspi gehängt. Das funktioniert wunderbar. Da reicht sogar eine 
Stromversorgung.

von 900ss (900ss)


Lesenswert?

Ich habe jetzt nicht geprüft, ob deine 40000 Pulse richtig sind. Aber 
40000 Pulse/Sek ergibt alle 25us ein Puls. Die Latenzzeit des RPi ist 
dafür zu langsam, deshalb verliert er Pulse. Selbst mit einem RPi3 und 
dem Linux-Realtimepatch wirst du das auf die Art nicht schaffen.

Hier sind Messungen mit einem RPi zu 
sehen:https://emlid.com/raspberry-pi-real-time-kernel/

Mit dem RPi3 wird es etwas besser sein aber wohl nicht ausreichen.

Wie oben schon erwähnt, mit Kernel-Mode-Treiber konnte es gehen.
Ansonsten einen kleinen AVR, wie vorgeschlagen.

: Bearbeitet durch User
von Marco H. (damarco)


Lesenswert?

Das trifft aber nur zu wenn der Code im Userspace läuft.  Da wird nichts 
anderes gemacht als die Abarbeitung in einen festgelegten Zeit zu 
garantieren.

Im Kernel selber werden Zeiten erstaunlich gut eingehalten.  Wenn dies 
nicht so wäre würden Probleme mit Hardware unausweichlich.

Um die Aufgabe zu lösen muss der Zeitkritische Teil im Kernel ablaufen. 
Wenn man sich auskennt ist die Aufgabe schon lösbar.

: Bearbeitet durch User
von Marco H. (damarco)


Lesenswert?

So ich habe etwas Zeit aufgebracht die Möglichkeiten des Kernel etwas 
auszuprobieren.

Hierzu habe ich ein Kernelmodul gebaut das den GPIO toggelt. Von außen 
lassen sich diverse Zeiten einstellen.

Mit den Timer Funktionen des Kernels respektive Timerliste lassen sich 
nur Zeiten bis 10ms realisieren. Die kleinst mögliche Zeit sind diese 
10ms das hängt mit dem Interrupt des Kernels zusammen. Die Liste wird 
wenn erforderlich alle 10ms abgearbeitet.

Mit den hrtimern geht mehr. Hier wird die Funktion sofort ausgeführt. 
Zeiten von 40µS sind machbar. Allerdings ist das System schon etwas 
schwerfällig. Zeiten drunter führen dazu das es nicht mehr reicht den 
hrtimer in die Zukunft zu stellen bevor dieser die Zeit zum auslösen 
erreicht. Das führt dazu das die Funktion sofort ausgeführt wird. Der 
Pin toggelt mit 500ns und das System ist kaum noch ansprechbar.


Also für das Problem ist es nicht ratsam das direkt im Kernel zu lösen. 
10ms oder mehr sind überhaupt kein Problem mit dem hrtimer werden diese 
extrem gut eingehalten.

Die mögliche Lösung wäre dies über DMA zu realisieren. Das geht aus dem 
Userspace . http://abyz.co.uk/rpi/pigpio/download.html

"sampling and time-stamping of GPIO 0-31 between 100,000 and 1,000,000 
times per second. "

Du sampelst den GPIO per DMA ein Beispiel mit einen Encoder gibt es dort 
auch.

von 900ss (900ss)


Lesenswert?

Du hast einen hrtimer mit weniger als 40us Interrupts ausführen lassen? 
Super Idee um den RPi lahmzulegen ;-)

Das kann man nur mit GPIO IRQs lösen bei der hohen Auflösung. Also immer 
wenn ein Flankenwechsel stattfindet, einen IRQ, der die Eingänge liest 
und die Zähler entsprechend anpasst. Pollend im Timer-IRQ ist das wohl 
kaum zu machen.
Hier hat das jemand mit IRQs gemacht.

https://sites.google.com/site/hamlinhomeprojects/projects/raspberry-pi-isr

Damit sollte könnte funktionieren.
Allerdings muss man dafür sorgen, das da nicht ein Kontakt auf 
"Dauerprellen" steht, sonst steht der RPi auch.

von 900ss (900ss)


Lesenswert?


von Nils P. (torus)


Lesenswert?

Niko U. schrieb:
> Von CPLDs habe ich noch nichts gehört :) Auf den ersten Blick hört sich
> das definitiv nach einer Lösung an, ich würde aber aus Zeitgründen
> lieber auf eine fertige Lösung zurückgreifen.

Nur keine Scheu. Auch CPLDs sind kein Hexenwerk, insbesondere bei solch 
kleinen Aufgaben nicht.

Wenn Du einigermaßen fitt bist, hast Du an einem Wochenende die 
Toolchain installiert und bist soweit eine LED blinken zu lassen. Dann 
den Decoder und ein (z.B.) SPI Interface zu implementieren dauert 
vielleicht 4 weitere Tage (mit dem nötigsten VHDL lernen).

Und danach hast Du die Technologie mal benutzt und keine Angst mehr 
davor. Es lohnt sich, echt!

: Bearbeitet durch User
von Marco H. (damarco)


Lesenswert?

Alternative wäre ein xmos. Ist zwar kein FPGA aber eine auf Echtzeit 
getrimmte MCU und lässt in C Programmieren.

von m.n. (Gast)


Lesenswert?

Falls Du noch nichts gefunden hast: 
Beitrag "mini Quadraturdekoder + 32 Bit Zähler + TWI, Attiny25"
Der Indeximpuls wird auch ausgewertet.

von Niko U. (Gast)


Lesenswert?

Hey,

danke nochmal für euer überragendes Feedback :) Das ist ja echt 
unglaublich :D

Also, da es schnell gehen soll (die Zeit für meine Masterarbeit ist 
leider begrenzt...), habe ich mich jetzt für den LS7366R entschieden. 
Der ist auch in Deutschland erhältlich:

http://www.macnica.eu/de/lsi/csi

(ob man da als Privatkunde bestellen kann, ist die andere Frage).

Die schnellere Variante:
http://www.mouser.de/ProductDetail/MikroElektronika/MIKROE-1917/?qs=%2fha2pyFadujB117G9yeeSZHQKrX2qpppY2A13zdz4KA%3d

Dann sitzt das ganze Zwar auf einer überdimensionierten Platine, aber 
für den Testaufbau wirds erstmal reichen :)

In dem Sinne,

ein angenehmes Wochenende :)

von Marco H. (damarco)


Lesenswert?


: Bearbeitet durch User
von Falk B. (falk)


Lesenswert?

@Marco H. (damarco)

>Das geht auch einfacher
>http://de.farnell.com/xmos/xk-stk-a8dev/dev-board-...

Welche Drogen nimmst du? Das Board vom OP schließt man an SPI an, Daten 
gemäß Datenblatt auslesen, fertig. Den Controller muss man noch 
programmieren, dazu muss man sich einarbeiten, das dauert hne spezielle 
Vorkenntnisse locker 1-4 Wochen!

Leute gibt's . .  .

von Marco H. (damarco)


Lesenswert?

Viel billiger wenn man das externe Board was man bauen muss noch 
berücksichtigt.

Für 14€ ist das unschlagbar. Denn mit dem Xmos lässt sich viel mehr 
anstellen. Man könnte auch einen Ethernet Slice drauf stecken und die 
Werte sogar mit PTP versenden. Mit dem RPI undenkbar.  Auch die 
Auswertung und Steuerung könnte man in dem Xmos quasi in Echtzeit 
realisieren.

Per SPI und optionalen Kernel Modul lassen sich die Dinge die man in RPI 
braucht übertragen.

Denn der Hintergedanke ist das man ja die Werte z.Bsp zum Regeln relativ 
schnell und mit kalkulierbarer Latenz benötigt. Vorgänge in dem Xmos 
sind Zeitlich Planbar. Ähnlich wie bei einen FPGA.

Zumal ist die Technologie recht interessant ;) Außerdem in C 
Programmierbar.

: Bearbeitet durch User
von Niko U. (Gast)


Lesenswert?

Kurzes feedback:

Die von mir gewählte Variante läuft einwandfrei :) Hat mich einen Tag 
arbeit gekostet und läuft wie gewünscht :D

danke nochmal an alle für euer Feedback :)

VG

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.