Hallo zusammen! Ich bin neu hier und habe schon unzählige Forenbeiträge und Tutorials durchgelesen, aber noch keine Lösung für mein Problem gefunden... Ich muss einen Prüfstand für eine Funktionseinheit realisieren, welche u.a. aus einem 24Volt DC-Motor mit Getriebe besteht, der eine Welle antreibt. Auf dieser Welle sind mehrere unterschiedliche Kurvenscheiben montiert, auf deren Außenkanten Kugellager mittels Stahlfedern gedrückt werden. Dreht sich nun die Welle mit den Kurvenscheiben, laufen die Kugellager auf der Kurvenscheibe entlang und betätigen dann irgendwelche Hebel. Die Welle macht pro Zyklus eine Umdrehung. Die Nullstellung der Welle wird über einen induktiven Initiator detektiert, welcher von einer Nockenscheibe betätigt wird, die sich ebenfalls auf der Welle befindet. Der Motor wird je nach Stellung der Welle unterschiedlich belastet(aufgrund der unterschiedl. Kurvenscheiben). Um nun herauszufinden, ob möglicherweise zu starke/zu schwache Federn montiert wurden, kann man ja über den Motorstrom eine Aussage über das Drehmoment treffen (Proportionalität). Ich muss also den Motorstrom aufzeichnen und dann mit einer zuvor definierten Hüllkurve vergleichen. Eckdaten: 24 Volt DC Motor, Dunker-BG65SI, eingebauter Speedcontroller mit spezieller Firmware / Getriebe 19:1 Die Motor-Firmware wurde so konzipiert, dass der Motor über zwei digitale Ausgänge zwei 24 Volt Hall Signale liefert, welche um 90° verschoben sind. Pro Motorumdrehung erhält man pro Hallspur 5 positive und 5 negative Flanken. Bei zwei Hallspuren macht das dann 20 Flankenwechsel. In Verbindung mit dem Getriebe erhalte ich dann 19*20 = 380 Signalwechsel pro Zyklus (Wellenumdrehung). Diese 380 Signalwechsel kann ich in Verbindung mit dem Grundstellungsinitiator zählen und daraus die aktuelle Position der Welle ermitteln. Und zu jeder einzelnen Position muss ich einen dazugehörigen Motorstrom messen und aufzeichnen. Dazu benutze ich den Stromsensor LEM LTS 15-NP. Vorgehen: Mit Hilfe eines Arduino Due die Hallsignale, den Grundstellungsinitiator und den Motorstrom erfassen (mit zusätzlicher Vor-Beschaltung). Diese Werte an dem Serial Monitor ausgeben lassen. Jetzt zu meinem Problem: Ein Zyklus dauert ca. eine Sekunde. Da die Übertragung der Daten vom Arduino mit 9600 Baud erfolgt, erhalte ich nur ca. 50 Wertepaare, welche überhaupt nicht brauchbar sind. Das Problem ist eben, dass ich die Daten direkt übertrage. Plan: Bei jedem der 380 Flankenwechsel eine Interruptroutine ausführen, welche den dazugehörigen Stromwert detektiert und das ganze im RAM speichern. Erst nach einem kompletten Zyklus dann die 380 Wertepaare über die serielle Schnittstelle schicken. Im Anhang befindet sich der bisherige Quellcode und eine Excel Datei mit den erhaltenen Daten (die Skala des Motorstroms passt noch nicht, Initiator und Hallsignale sind binär). Außerdem noch der Motorstromverlauf, welcher mit einer Stromzange (Oszi) aufgenommen wurde. Wenn man beide Stromverläufe vergleicht, sieht man, dass die Messung über Stromzange(Oszi) um ein vielfaches genauer ist, als die Daten des Arduino. Ich benötige also einen Quellcode, mit welchem man eine ähnliche Genauigkeit erreicht als mit der Stromzange… Leider habe ich keine Ahnung, wie ich das ganze umsetzen/ implementieren kann, weshalb ich mich an euch wende. Ich bin wirklich für jede Hilfe dankbar!
Hallo, soweit ich weiß, kann man die Daten auch schneller aus dem Arduino herausbekommen. Bis 115200 baud wird direkt von der Arduino Library angegeben (http://arduino.cc/en/Serial/begin).
1 | Serial.begin(115200); |
Angeblich kann man auch mehr herausholen. http://forum.arduino.cc/index.php?topic=21497.0 Du musst natürlich die Gegenstelle (also den PC der die Daten empfängt) auch entsprechend umstellen. Alternativ kannst du natürlich immer einfach vorher die Werte intern speichern und anschießend übertragen. Quellcode nur exemplarisch (Quelle [1]):
1 | unsigned long values[1000]; |
2 | |
3 | void loop() { |
4 | unsigned int i; |
5 | |
6 | // capture the values to memory
|
7 | for(i=0;i<1000;i++) { |
8 | values[i] = analogRead(2); |
9 | }
|
10 | |
11 | // print out the results
|
12 | Serial.println("\n\n--- Results ---"); |
13 | for(i=0;i<1000;i++) { |
14 | Serial.print(values[i]); |
15 | }
|
16 | }
|
Achtung: es könnte sein, dass der ADC die 1000 Werte deutlich schneller eingelesen hat als eine Umdrehung deiner Welle (von der du die Daten haben willst) dauert. Das solltest du aber anhand der anderen Signale gut sehen können. Liebe Grüße, Lui [1] http://www.microsmart.co.za/technical/2014/03/01/advanced-arduino-adc/
Carl-Josef S. schrieb: > Da die > Übertragung der Daten vom Arduino mit 9600 Baud erfolgt, erhalte ich nur > ca. 50 Wertepaare, welche überhaupt nicht brauchbar sind. Mit dem Arduino gehen locker 250.000 und auch 500.000 Baud, damit sollten mind. 10.000 Samples/s und weit mehr gehen. Ich habe mit einem Arduino Uno bei 500.000 Baud ca. 30.000 Samples/s (je 8bit binary) geschaft. Allerdings nicht mit den schnarchigen Arduino Libs, sonder mit LunaAvr. Mit Deinem Arduino Due müsste das trotz der langsamen Arduino Libs event. auch gehen. An Deiner Stelle würde ich aber den Due entsorgen, einen Uno nehmen und dazu eine Programmiersprache, die alle Funktionen/Ports des MC sofort ansprechen kann, wie C, Luna, Bascom. Dann bist Du warscheinlich immer noch schneller als mit dem Due und den Arduino Libs.
:
Bearbeitet durch User
Peter Luidolt schrieb: > Du musst natürlich die Gegenstelle (also den PC der die Daten empfängt) > auch entsprechend umstellen. Das ist Unsinn, an den ComPorts im PC muss man nichts umstellen, die Einstellungen sind absolut schnuppe. Ich wechsele die Baudraten vom MC beim Testen dauernd, ohne im PC-Gerätemanager die ComPort Baudraten umzustellen. Die stehen auf 9.600 Baud obwohl z.B. mit 500.000 Baud übertragen wird. Da schaut man höchstens nach um die aktuell benutzte Port-Nummer zu sehen.
:
Bearbeitet durch User
Albert M. schrieb: > Das ist Unsinn, an den ComPorts im PC muss man nichts umstellen, die > Einstellungen sind absolut schnuppe. Das ist überhaupt kein Unsinn. Du redest von Comports und da muss man die Baudrate definitiv umstellen. Wahrscheinlich meinst du virtuelle Comports (über USB). Bei denen funktioniert das so.
avr schrieb: > Das ist überhaupt kein Unsinn. Du redest von Comports und da muss man > die Baudrate definitiv umstellen. Wahrscheinlich meinst du virtuelle > Comports (über USB). Bei denen funktioniert das so. Und was meinst Du welche Art von ComPorts von den Arduino Treibern generiert werden? Ja eben, virtuelle ComPorts, was sonst. Also ist Dein Gerede vom Umstellen müssen für den TO irrelevant.
:
Bearbeitet durch User
Hallo!
Erstmal DANKE für die Antworten.
Ich werde als nächstes die geposteten URLs durchschauen und dann mal die
Baudrate erhöhen und etwas rumprobieren. Werde dann wieder ein
Bild(Excel) von den neuen Wertepaaren schicken.
>An Deiner Stelle würde ich aber den Due entsorgen, einen Uno nehmen...
Das verstehe ich nicht ganz. Hab mir extra noch einen Due zugelegt, da
der ja viel bessere Leistungsdaten hat(Geschwindigkeit, RAM,...). Habe
aber auch noch einen Uno und einen Mega zur Verfügung.
Carl-Josef S. schrieb: > Flankenwechsel. In Verbindung mit dem Getriebe erhalte ich dann 19*20 = > 380 Signalwechsel pro Zyklus (Wellenumdrehung). Kannst Du irgendwas zu Ablaufgeschwindigkeit oder Drehzahl sagen? In welcher Zeit kommen diese 380 Signalwechsel? > Und zu jeder einzelnen Position muss ich einen > dazugehörigen Motorstrom messen und aufzeichnen. Wenn Du das musstt, solltest Du das auch machen. Dein bisheriger Code macht das nicht. Insbesondere mißt und sendet Dein Code nicht beim Auftreten eines Flankenwechsels, sondern "mit maximaler Geschwindigkeit". Dadurch läuft Dir der serielle Sendepuffer zu und dann kannst Du alle gesendeten Werte vergessen. Der erste Flaschenhals Deines Programms ist die serielle Schnittstelle. Die Anzahl der Zeichen, die Du pro Sekunde senden kannst, beträgt Baudrate geteilt durch 10. Bei 9600 Baud wären dass max. 960 Zeichen/s. Bei 115200 Baud (max. Baudrate des "Seriellen Monitor" von Arduino) wären es 11520 Zeichen/s, Bei 500000 als maximale Baudrate eines Arduino UNO (nur mit anderen Terminalprogrammen auf dem PC nutzbar) wären es 50000 Zeichen/s. Welches die maximale Baudrate eines DUE ist, weiß ich nicht. > Im Anhang befindet sich der bisherige Quellcode Sende den Quellcode lieber zwischen Code-Tags oder als Dateianhang. > mit den erhaltenen Daten (die Skala des Motorstroms passt noch nicht, > Initiator und Hallsignale sind binär). Wie gesagt: Solange Du versuchst, die serielle Schnittstelle zu überdrehen kannst Du alles vergessen. Wenn Du die Signale immer zu dem Zeitpunkt benötigst, zu dem bei den Hallsignalen ein Flankenwechsel auftritt, solltest Du genau diese Flanken auswerten und beim Flankenwechsel den Stromsensor auslesen und den Wert senden. Das benötigt keine Interrupt-Routine.
Hallo Jürgen, > Carl-Josef S. schrieb: >> Flankenwechsel. In Verbindung mit dem Getriebe erhalte ich dann 19*20 = >> 380 Signalwechsel pro Zyklus (Wellenumdrehung). > > Kannst Du irgendwas zu Ablaufgeschwindigkeit oder Drehzahl sagen? > In welcher Zeit kommen diese 380 Signalwechsel? Das hat er irgendwo oben im Text versteckt, 1 U/s, also 380 Hz für die Messungen bzw. die Hallsignale. Dafür sind 9600 Baud klar zu wenig, sobald mehr als ein paar Byte pro Messung übertragen werden sollen. Mit freundlichen Grüßen Thorsten Ostermann
Hallo! Ich habe nochmal ein Messversuch mit höherer Baudrate (115200) durchgeführt und das Resultat sieht schon besser aus (Anhang). Jedoch hat Jürgen S recht, dass ich nicht die positionsbezogenen Motorströme erhalte, sondern einfach nur mit maximaler Taktung die Werte übertrage. Ich habe dann das Programm nach Vorlage von "Peter Luidolt (luidoltp)" umgeschrieben, aber das funktioniert noch nicht (Anhang). Da muss ich morgen noch etwas herumprobieren. Falls jemand weiß, wie ich das Programm verändern muss, wäre ich sehr dankbar. Im Moment bekomme ich zwar Werte über den "Serial Monitor" angezeigt, jedoch ändern sich diese nicht. Wenn ich die Zählvariable "i" auf 5 (statt auf 500) stelle, bekomme ich eben fünf mal die gleichen Wertepaare und das immer fortwährend. Bei i=500 kommen eben 500 mal die gleichen,unveränderten Werte und dann beginnt es wieder von vorne (mit "---Results---").( Motor wurde während der Messung angesteuert).
Carl-Josef S. schrieb: > Ich habe nochmal ein Messversuch mit höherer Baudrate (115200) > durchgeführt und das Resultat sieht schon besser aus (Anhang). > Jedoch hat Jürgen S recht, dass ich nicht die positionsbezogenen > Motorströme erhalte, sondern einfach nur mit maximaler Taktung die Werte > übertrage. Ich habe Dir mal ein neues Programm gemacht, das immer nur beim Flankenwechsel an den Drehgeberausgängen eine Messung macht.
1 | const int analogInPin = A0; // Analog input pin that the LEM LTS 15-NP is attached to |
2 | int IniB13 = 2; //Grundstellung |
3 | int Hall1 = 3; //Hallspur 1 |
4 | int Hall2 = 4; //Hallspur 2 |
5 | |
6 | |
7 | void setup() { |
8 | Serial.begin(115200); |
9 | pinMode (IniB13, INPUT); |
10 | pinMode (Hall1, INPUT); |
11 | pinMode (Hall2, INPUT); |
12 | analogReadResolution(12); //Auflösung auf 12 Bit erhöhen |
13 | }
|
14 | |
15 | static boolean grundStellungsImpuls() |
16 | // Flankenwechselerkennung Grundstellung
|
17 | {
|
18 | static byte lastStellung; // letzte Stellung in statischer Variablen merken |
19 | boolean result; |
20 | byte stellung=digitalRead(IniB13); // aktuelle Stellung auslesen |
21 | if (stellung==HIGH && lastStellung==LOW) result=true; // Flankenwechsel auf HIGH? |
22 | else result=false; |
23 | lastStellung=stellung; // aktuell ausgelesene Stellung merken |
24 | return result; |
25 | }
|
26 | |
27 | static boolean hallSensorImpuls() |
28 | // Flankenwechselerkennung an den Drehgeberausgängen
|
29 | {
|
30 | static byte lastA, lastB; |
31 | boolean result=false; |
32 | byte nowA=digitalRead(Hall1); |
33 | byte nowB=digitalRead(Hall2); |
34 | if (nowA!=lastA || nowB!=lastB) result=true; |
35 | lastA=nowA; |
36 | lastB=nowB; |
37 | return result; |
38 | }
|
39 | |
40 | |
41 | int stepcounter=0; |
42 | |
43 | void loop() { |
44 | if (grundStellungsImpuls()) stepcounter=0; |
45 | if (hallSensorImpuls()) |
46 | {
|
47 | int strom = analogRead(analogInPin); //Analogwert von Stromsensor |
48 | stepcounter++; |
49 | Serial.print(stepcounter); |
50 | Serial.print("\t"); |
51 | Serial.print(strom); |
52 | Serial.print('\n'); |
53 | }
|
54 | }
|
Da pro Messung eine Zeile auf Serial mit der Drehstellung ("stepcounter") und dem Messwert ausgegeben wird, entsprechend ca. 10 Zeichen pro Messung, sollten bei 380 Impulsen pro Sekunde ca. 3800 Zeichen pro Sekunde auf der seriellen Schnittstelle auszugeben sein. Wobei man bei 115200 Baud bis zu 11520 Zeichen ausgeben könnte. Passt also für Realtime-Ausgabe. Beim Setzen der ADC-Auflösung mit "analogReadResolution(12);" bin ich mal davon ausgegangen, dass das nicht vor jeder Messung gemacht werden muss, und es daher in die setup-Funktion verschoben. Ich kenne mich mit dem DUE nicht aus, wenn nicht, schiebe die Zeile in die loop zurück. Beim "grundStellungsImpuls()" habe ich eine Flankenerkennung gemacht, die vom Übergang Low-nach-High reagiert und dann den Schrittzähler zurücksetzt. Das kann man ggf. einfach auf die andere Flanke umprogrammieren. Etwas mehr Aufwand wäre es, wenn Schritt 1 irgendwo in der Mitte auftreten würde, aber auch das wäre machbar, die Schrittzählung auf einen anderen Nullpunkt zu setzen. Kannst ja mal bei Bedarf damit testen. Falls Du dabei feststellen solltest, dass der Stepcounter höher als bis 380 läuft, dann prellen die Ausgänge Deiner Hallsensoren und die Schrittzählung ist nicht zuverlässig. In dem Fall müßte man statt der Flankenwechselerkeunnung eine richtige Drehgeberauswertung machen und die Impulse vor- und rückwärts zählen, um das Prellen aus den Signalen zu eliminieren.
Albert M. schrieb: > Und was meinst Du welche Art von ComPorts von den Arduino Treibern > generiert werden? Ja eben, virtuelle ComPorts, was sonst. Also ist Dein > Gerede vom Umstellen müssen für den TO irrelevant. Hier geht es nicht nur um den TO, sondern auch um andere, die das später lesen. Und so wie dein Beitrag da steht ist er einfach inhaltlich falsch. Das kleine Wörtchen virtuell macht nämlich einen gewaltigen Unterschied aus.
Hallo! Zu der "Diskussion" über ComPorts kann ich mich nicht wirklich beteiligen, davon verstehe ich zu wenig. Ich habe jedenfalls nur im Arduino-Sketch die Baudrate erhöht und bekam so eine bessere Auflösung der Messung. In der Systemsteuerung des PC habe ich nichts verändert. @ Jürgen S: Vielen Dank für dein Programmcode. Habe ihn nur auf "Flankenwechsel auf LOW" ändern müssen. Das Problem ist jetzt nur, dass der Motor für eine Wellenumdrehung keine kontinuierliche Bewegung ausführt, sondern in fünf unterschiedlichen Positionen kurz anhält. Wenn er dann wieder anläuft aus der jeweiligen Position, bekomme ich einen relativ hohen und steilen Strompeak. Das kann man in dem Bild sehen, welches ich mit dem Oszi und der Stromzange (siehe Anfangsbeitrag, LeCroy.png)gepostet habe. Mit dem Programmcode von Jürgen S bekomme ich immer ein Stromwert geliefert, wenn sich eine der beiden Hallspuren ändert (=wenn sich der Motor bewegt). Die Peaks treten aber in dem Anlaufmoment auf, kurz bevor eine Motorbewegung stattfindet. Deshalb werden sie nicht (immer) in voller Höhe erfasst. Außerdem verharrt der Motor kurz in den fünf unterschiedlichen Positionen und während dieser Zeit wird auch kein Stromwert detektiert (weil kein Hall-wechsel). Es ist also nicht wirklich möglich (bzw.aussagekräftig), positionsbezogene Ströme zu erfassen und mit einer zuvor definierten Hüllkurve zu vergleichen. Mir bleibt jetzt noch die Möglichkeit, den Bewegungsablauf so abzuändern, dass der Motor eine gleichmäßige Bewegung mit konstanter Geschwindigkeit ausführt. Dies entspricht zwar nicht dem späteren Bewegungsablauf, aber für den Prüfstand ist das erst mal egal. Hier geht es ja nur darum, eventuelle Montagefehler zu erkennen. Probleme könnten sich jetzt nur ergeben, dass ich keine 100%ig gleichmäßige Umdrehungsgeschwindigkeit realisieren kann, da der Motor ja unterschiedlich belastet wird-je nach Position der Welle aufgrund der unterschiedlichen Kurvenscheiben. Möglichkeit 2: alle positiven Ströme einer Umdrehung addieren und der Gesamtwert muss dann in einem bestimmten Bereich liegen ( und das gleiche mit negativen Strömen auch machen). Sollte der Gesamtwert zu hoch sein, kann man davon ausgehen, dass etwas klemmt oder zu starke Federn montiert wurden. Ich weiß aber nicht, wie groß hier der Toleranzbereich gewählt werden muss. ...Ich habe also die nächsten Tage noch einiges an Messversuchen etc. vor mir. Werde euch auf dem Laufenden halten. Falls jemand eine Idee hat, welche Möglichkeiten ich noch habe, den Motorstrom zu erfassen und v.a. auszuwerten- ich bin für jeden Tipp/Hilfe dankbar!
Carl-Josef S. schrieb: > Das Problem ist jetzt nur, dass > der Motor für eine Wellenumdrehung keine kontinuierliche Bewegung > ausführt, sondern in fünf unterschiedlichen Positionen kurz anhält. Wenn > er dann wieder anläuft aus der jeweiligen Position, bekomme ich einen > relativ hohen und steilen Strompeak. Das kann man in dem Bild sehen, > welches ich mit dem Oszi und der Stromzange (siehe Anfangsbeitrag, > LeCroy.png)gepostet habe. Mit dem Programmcode von Jürgen S bekomme ich > immer ein Stromwert geliefert, wenn sich eine der beiden Hallspuren > ändert (=wenn sich der Motor bewegt). Die Peaks treten aber in dem > Anlaufmoment auf, kurz bevor eine Motorbewegung stattfindet. Deshalb > werden sie nicht (immer) in voller Höhe erfasst. OK, Du brauchst also sehr viel mehr Samples mit sehr viel kürzeren Zeitabständen. Um den Flaschenhals "Serial" zu umgehen, dann also doch wieder zurück zu Deiner ersten Idee: Erst schnell die Werte in den RAM-Speicher sampeln, und dann die Werte ausgeben. Du verwendest ja den DUE und der hat erhebliche Mengen RAM-Speicher, da sollte das kein Problem sein. > Motor kurz in den fünf unterschiedlichen Positionen und während dieser > Zeit wird auch kein Stromwert detektiert (weil kein Hall-wechsel). Es > ist also nicht wirklich möglich (bzw.aussagekräftig), positionsbezogene > Ströme zu erfassen und mit einer zuvor definierten Hüllkurve zu > vergleichen. OK, ich habe mal einen geänderten Sketch gemacht, der nicht positionsbezogen sampelt, sondern zeitbezogen, und zwar zunächst mal "so schnell wie möglich". Das Sampling wird getriggert durch: - Erkennung des Impulses für die Grundstellung - Auf einen frei wählbaren Step-Impuls der Hall-Sensoren Das ist in der loop-Funktion diese Zeile:
1 | if (waitForStart && stepcounter==4) // Triggern auf einen bestimmten Impuls |
Falls nach diesem Triggerimpuls zunächst eine uninteressante Standzeit auftritt, kann dort ein optionales delay die Sampling-Aufzeichnung verzögert starten. Und falls die Samplings zu schnell aufeinander folgen, kann in der recordSamples() Funktion ein kleines Mikrosekunden-delay in der Einleseschleife eingefügt werden, um die Aufzeichnungsdauer zu strecken. Vollständiger Code:
1 | const int analogInPin = A0; // Analog input pin that the LEM LTS 15-NP is attached to |
2 | int IniB13 = 2; //Grundstellung |
3 | int Hall1 = 3; //Hallspur 1 |
4 | int Hall2 = 4; //Hallspur 2 |
5 | |
6 | struct sample_t{ |
7 | uint16_t time; // Zeit in Mikrosekunden nach Startimpuls |
8 | uint16_t stepcount; // Schritte vom Drehgeber |
9 | int16_t strom; // ADC-Messwert |
10 | };
|
11 | |
12 | #define NUMSAMPLES 5000
|
13 | |
14 | sample_t samples[NUMSAMPLES]; |
15 | |
16 | void setup() { |
17 | Serial.begin(115200); |
18 | pinMode (IniB13, INPUT); |
19 | pinMode (Hall1, INPUT); |
20 | pinMode (Hall2, INPUT); |
21 | analogReadResolution(12); //Auflösung auf 12 Bit erhöhen |
22 | }
|
23 | |
24 | static boolean grundStellungsImpuls() |
25 | // Flankenwechselerkennung Grundstellung
|
26 | {
|
27 | static byte lastStellung; // letzte Stellung in statischer Variablen merken |
28 | boolean result; |
29 | byte stellung=digitalRead(IniB13); // aktuelle Stellung auslesen |
30 | if (stellung==LOW && lastStellung==HIGH) result=true; // Flankenwechsel auf LOW? |
31 | else result=false; |
32 | lastStellung=stellung; // aktuell ausgelesene Stellung merken |
33 | return result; |
34 | }
|
35 | |
36 | static boolean hallSensorImpuls() |
37 | // Flankenwechselerkennung an den Drehgeberausgängen
|
38 | {
|
39 | static byte lastA, lastB; |
40 | boolean result=false; |
41 | byte nowA=digitalRead(Hall1); |
42 | byte nowB=digitalRead(Hall2); |
43 | if (nowA!=lastA || nowB!=lastB) result=true; |
44 | lastA=nowA; |
45 | lastB=nowB; |
46 | return result; |
47 | }
|
48 | |
49 | void recordSamples(int &stepcounter) |
50 | {
|
51 | int i; |
52 | unsigned long startZeit=micros(); |
53 | for (i=0;i<NUMSAMPLES;i++) |
54 | {
|
55 | samples[i].time=micros()-startZeit; |
56 | samples[i].strom= analogRead(analogInPin); //Analogwert von Stromsensor |
57 | samples[i].stepcount=stepcounter; |
58 | if (hallSensorImpuls()) stepcounter++; |
59 | // delayMicroseconds(100);
|
60 | }
|
61 | }
|
62 | |
63 | |
64 | void showSamples() |
65 | {
|
66 | int i; |
67 | int timeOverflow=0; |
68 | float ftime; |
69 | for (i=0;i<NUMSAMPLES;i++) |
70 | {
|
71 | if (i>0 && samples[i].time<samples[i-1].time) timeOverflow++; |
72 | ftime=samples[i].time/1000000.0+timeOverflow*65536.0/1000000.0; |
73 | Serial.print(i+1); |
74 | Serial.print("\t"); |
75 | Serial.print(ftime,6); |
76 | Serial.print("\t"); |
77 | Serial.print(samples[i].stepcount); |
78 | Serial.print("\t"); |
79 | Serial.print(samples[i].strom); |
80 | Serial.print('\n'); |
81 | }
|
82 | Serial.flush(); |
83 | }
|
84 | |
85 | |
86 | |
87 | int stepcounter=0; |
88 | boolean waitForStart=false; |
89 | |
90 | void loop() { |
91 | if (grundStellungsImpuls()) |
92 | {
|
93 | stepcounter=0; |
94 | waitForStart=true; |
95 | }
|
96 | if (waitForStart && stepcounter==4) // Triggern auf einen bestimmten Impuls |
97 | {
|
98 | // delay(10); // Optional ein delay zur Überbrückung einer uninteressanten Standzeit
|
99 | recordSamples(stepcounter); |
100 | showSamples(); |
101 | waitForStart=false; |
102 | }
|
103 | if (hallSensorImpuls()) stepcounter++; |
104 | }
|
Ich habe die Anzahl der Samples mal auf 5000 gesetzt, und da jedes Sample 6 Bytes belegt, sollten die Samples im Array ca. 30 KB RAM benötigen, was auf einem DUE ja locker möglich ist. > Falls jemand eine Idee hat, welche Möglichkeiten ich noch habe, den > Motorstrom zu erfassen und v.a. auszuwerten- ich bin für jeden > Tipp/Hilfe dankbar! Probier's mal aus mit den schnellen Samplings ab einem bestimmten Schritt! Wie gesagt, nach Starten des Sketches muß einmal der grundStellungsImpuls() erfolgen, und dann wird das Sampling für die Anzahl der definierten Samples gestartet, sobald die Hallsensoren den gewünschten Schritt erreicht haben. Nach dem Sampeln werden die Daten sofort auf Serial ausgegeben. Der Zeitstempel läuft in dem Sketch ab Start der Aufzeichnung und wird zur Ausgabe auf Serial in Sekunden mit sechs Nachkommastellen (Mikrosekunden) umgerechnet. Falls Du irgendwelche Fragen hast, einfach fragen.
Hallo!
Erstmal wieder ein großes DANKE an Jürgen.
Ich habe den neuen Quellcode ausprobiert und den Trigger auf
stepcounter==40 gesetzt. Ich bekomme dann ab dem 40. Hallwechsel 5000
Samples ausgegeben. Das Problem ist jetzt nur, dass die 5000 Samples nur
von stepcounter==40 bis stepcounter = 79 reichen(Anhang). Das heißt,
dass 39 Hallwechsel auf 5000 Wertepaare aufgelöst werden.
Ich habe dann mal die Samples erhöht, aber mehr als 10000 Samples ist
nicht möglich. Ab ca. 11000 Samples bekomme ich eine Fehlermeldung, dass
irgendwas außerhalb des RAM liegt. Des Weiteren bekomme ich bei 10000
Samples nur 83 Hallwechsel. Das liegt daran, weil bei stepcounter = 82
der Motor kurz anhält (insgesamt 0,029062 Sekunden) und ich aber
(zeitabhängig) insgesamt 3720 Samples für diesen Zeitraum
bekomme(Anhang).
Ich habe mich außerdem beim Startbeitrag leicht geirrt. Das Getriebe ist
kein 19:1 sondern ein 34:1. Das heißt, dass ich 680 Hallsignalwechsel
pro Wellen-Umdrehung erhalte.
...
Ich bin zu dem vorläufigen Ergebnis gekommen, dass es wahrscheinlich das
Beste wäre, den Motor mit gleichbleibender Geschwindigkeit anzusteuern
und dann zeitabhängig z.B. alle 1ms eine Messung zu machen. Wenn ich
also die Drehzahl verringere, dass eine Wellenumdrehung ca. zwei bis
drei Sekunden dauert (und das ganze bei einer konstanten
Geschwindigkeit), erhalte ich pro Wellenumdrehung 3000 Werte (bei 1ms
Abtastrate). Es sollte also möglich sein, den Motor kontinuierlich
laufen zu lassen, und erst ab der (z.B.) dritten oder vierten
Wellenumdrehung (dem dritten/vierten Flankenwechsel des
Grundstellungsinis von HIGH auf LOW) eine Messung von drei weiteren
Wellenumdrehungen aufzuzeichnen mit einer festen Abtastrate von 1ms.
Das bisherige Problem wird dadurch hoffentlich etwas entschärft, dass
ich relativ steile und gleichzeitig sehr schmale Strompeaks erfassen
muss. Durch eine zeitgetriggerte Abtastung kann es zwar immer noch
passieren, dass ich nicht die Spitze des Peaks erfasse (sondern kurz
davor messe und dann wieder kurz danach), aber eine andere(bessere)
Möglichkeit fällt mir gerade nicht ein. Durch die langsamere und v.a.
gleichmäßige Drehzahl hoffe ich, dass die Peaks nicht mehr so steil
sind, da der Motor ja nicht mehr aus der Ruhelage beschleunigen/bremsen
muss. Eine 100%ig gleichmäßige Geschwindigkeit wird nicht realisierbar
sein, da der Motor durch die unterschiedlichen Kurvenscheiben nicht
konstant belastet wird, aber einigermaßen konstant sollte klappen. Ich
habe mir zu diesem Zweck eine SPS besorgt, bei der ich mithilfe eines
Poti ein Analogwert von 0-10 Volt ausgeben lassen kann. Dieser
Analogwert steuert dann die Drehzahl des Motors. Werde aber frühestens
morgen dazu kommen, das ganze zu verdrahten und dann auszuprobieren.
Sollte jemand noch eine andere Möglichkeit einfallen, ich bin für jede
Inspiration dankbar.
>Falls Du irgendwelche Fragen hast, einfach fragen.
Wenn du Zeit und Lust hast, würdest du mir wieder helfen beim Quellcode
zur zeitabhängigen Abtastung der Stromwerte? Wäre dir wirklich sehr
dankbar...
Carl-Josef S. schrieb: > stepcounter==40 gesetzt. Ich bekomme dann ab dem 40. Hallwechsel 5000 > Samples ausgegeben. Das Problem ist jetzt nur, dass die 5000 Samples nur > von stepcounter==40 bis stepcounter = 79 reichen(Anhang). Das heißt, > dass 39 Hallwechsel auf 5000 Wertepaare aufgelöst werden. > Ich habe dann mal die Samples erhöht, aber mehr als 10000 Samples ist > nicht möglich. Irgendwann sind auch die 96 KB RAM eines Arduino DUE aufgebraucht. An RAM benötigen wie gesagt 5000 Samples ca. 30 KB, d.h. 10000 Samples ca. 60 KB RAM. > Ab ca. 11000 Samples bekomme ich eine Fehlermeldung, dass > irgendwas außerhalb des RAM liegt. Des Weiteren bekomme ich bei 10000 > Samples nur 83 Hallwechsel. Ich habe den Sketch ja erstmal auf möglichst schnelles Sampling gestellt. Wie lange dauern denn die 10000 Samples? Zeit in Sekunden wäre in der ersten Spalte der Serial-Ausgabe? Ich habe keinen DUE und weiß daher nicht, wie schnell die sind. > Ich bin zu dem vorläufigen Ergebnis gekommen, dass es wahrscheinlich das > Beste wäre, den Motor mit gleichbleibender Geschwindigkeit anzusteuern > und dann zeitabhängig z.B. alle 1ms eine Messung zu machen. Bei meinem zuletzt geposteten Sketch hatte ich die Stelle schon auskommentiert gepostet, wo Du das Sampling langsamer einstellen kannst, beim Einlesen der Samples:
1 | // delayMicroseconds(100);
|
Wenn Du hier die Kommentarstriche entfernst, bekommt jedes Sample ein
delay von 100 Mikrosekunden, mal 10000 Samples sind das 1 Mio
Mikrosekunden oder 1 Sekunde. D.h. mit diesem delay kannst Du es
steuern, in welcher Zeit die 10000 Samples gemacht werden. Mit 100µs
extra delay pro Sample wird auf jeden Fall länger als eine Sekunde nach
dem Triggern gesampelt. Kürzeres oder kein delay ==> 10000 Samples sind
schnell voll. Längeres delay ==> 10000 Samples dauern länger.
> Möglichkeit fällt mir gerade nicht ein.
Außerdem habe ich ja vorgegeben, dass Du das Sampeln bei einem
beliebigen "Stepcounter" beginnen lassen kannst. Dadurch kannst Du Dir
über verschiedene Vorgaben für den Trigger-Startwert in mehreren
Umläufen auch einen Gesamtumlauf zusammenstellen. Einmal mit
stepcounter==40 triggern, einmal mit stepcounter==80 triggern, einmal
mit stepcounter=120 triggern, und dann kopierst Du Dir die Daten manuell
zu einem vollen Umlauf zusammen.
Hallo! Ich habe jetzt zwei Tage verschiedene Messversuche gemacht... Um die Strompeaks in den Griff zu bekommen, werde ich dem Motor einen konstanten Analogwert vorgeben(3,3Volt des Arduinos). Mit diesem Wert erreiche ich ziemlich genau eine Wellenumdrehung des 34:1 Getriebes pro Sekunde (bei konstanter Geschwindigkeit). Als Prüfablauf habe ich mir folgendes vorgestellt: Ich steuere den Motor an, dass er im Dauerbetrieb läuft. Nach einer bestimmten Anzahl Umdrehungen ohne Messung (z.B. fünf) möchte ich dann von den drei darauffolgenden Umdrehungen den Strom messen (Motor läuft die ganze Zeit über im Dauerbetrieb). Erst nach Vollendung dieser drei Umdrehungen werden die Werte seriell übermittelt. Sollte der Motor irgendwann mal zwischen/während Startzeitunkt (den Umdrehungen ohne Messung) und dem Ende der Messung (nach den Umdrehungen ohne Messung UND den gemessenen Umdrehungen) kurz zum Stillstand kommen (zu große Zeitspanne zwischen zwei Hallwechsel), ist die Messung wertlos. In diesem Fall sollte eine Fehlermeldung ausgegeben werden, die Messwerte verworfen werden und das Programm bereit sein, für eine neue Messung. Wenn die eingestellten 10000 Samples nicht genügen sollten, um die Werte von drei kompletten Umdrehungen speichern zu können, d.h. die 10000 Samples sind nach 2,5 Umdrehungen schon fertig, soll ebenfalls eine Fehlermeldung kommen. Dann weiß ich, dass ich das delay etwas erhöhen muss. Wenn für drei Umdrehungen nur ca. 9300 Samples benötigt werden, sollen auch nur 9300 Samples übertragen werden. (Um eine aussagekräftige Auswertung durchführen zu können, benötige ich die Stromwerte von drei kompletten Umdrehungen, welche mit konstanter Geschwindigkeit ausgeführt wurden.) Wenn der Motor nach erfolgreich übermittelter Messung immer noch weiter läuft, soll das keine Auswirkung haben. Sobald er dann irgendwann stoppt, sollte das Programm nach einem delay von ca. 5 Sekunden wieder bereit sein, für eine neue Messung. Diese Zeit wird für die Übertragung der Daten benötigt. Zusammenfassung: Möglichkeit 1: Motor wird angesteuert und läuft mit (annähernd)konstanter Geschwindigkeit. Nach vier Umdrehungen stoppt der Motor kurz. =>Meldung "Messung fehlgeschlagen" =>Programm für neuen Prüfablauf bereit Möglichkeit 2: Motor wird angesteuert und läuft mit (annähernd)konstanter Geschwindigkeit. Nach sechs Umdrehungen stoppt der Motor kurz. Das heißt, er hat fünf Umdrehungen ohne Messung und eine Umdrehung mit Messung=>Meldung "Messung fehlgeschlagen" =>keine Daten seriell übertragen/Daten verwerfen =>Programm für neuen Prüfablauf bereit Möglichkeit 3: Motor wird angesteuert und läuft mit (annähernd)konstanter Geschwindigkeit. Nach (mehr als) acht Umdrehungen stoppt der Motor kurz. Das heißt, er hat fünf Umdrehungen ohne Messung und drei Umdrehung mit Messung=>Meldung "Messung erfolgreich" => Daten seriell übertragen=>Programm nach fünf Sekunden für neuen Prüfablauf bereit. Ich habe versucht,den Code von Jürgen auf den gewünschten Prüfablauf anzupassen, aber irgendwie bekomm ichs nicht hin. Im Moment werden nach dem fünften Flankenwechsel (von HIGH auf LOW) des Grundstellungsinis 10000 Samples aufgenommen und übertragen. Da ich ein delay von 200us eingestellt habe, bekomme ich also die Stromwerte der darauffolgenden zwei Sekunden. Wenn während der ersten fünf Umdrehungen der Motor (mehrmals) stoppt, werden trotzdem nach fünf Umdrehungen die Werte der darauffolgenden zwei Sekunden übertragen(es soll aber das passieren, was in Möglichkeit 1 beschrieben wurde). Wenn während der zwei Sekunden der Motor stoppt, werden trotzdem die Samples übertragen(es soll aber das passieren, was in Möglichkeit 2 beschrieben wurde). Irgendwie bekomm ich es nicht hin, den Motor zu überwachen, dass er sich mit konstanter Geschwindigkeit bewegt um dann damit die Freigabe für die Messung korrekt zu erteilen... Im Anhang befindet sich der derzeitige Code. Falls jemand eine Idee hat, wie ich die gewünschten Funktionen implementieren kann, wäre ich sehr dankbar.
Hallo allerseits, ich hatte auch schon das Problem (Ausgabe von uController-internen Mess-/Rechen-Zustandsgrößen). Die Serielle Schnittstelle ist zu langsam und vermutlich auch nicht rückwirkungsfrei (frißt Rechenzeit, was bei interruptgesteuerten Vorgängen das eigentliche Hauptprogramm komplett in die Knie zwingt). Als work-around hatte ich in meiner Anwendung (DC-Motor-Drehzahlregelung mit PID-Regler) zur Kontrolle alle relevanten Daten über die DA_Wandler-Kanäle ausgegeben. Der UNO gibt nur PWM-Muster aus, muß also somit mit einem RC-Glied noch befiltert werden. Vorteil: * lief mit Oszi-Auflösung bis 200ms / DIV relativ glatt durch (sollte also bei Deiner Motor-Applikation gut funktionieren) * visualisiert die Daten im Zeitbereich * erschiene mir - rein subjektiv- schneller als die serielle Schnittstelle Das ist sicherleich auch nicht die beste Lösung, aber vielleicht hat ja jemand noch eine bessere Idee. Miss Franken
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.