Moin Moin,
vorne weg, das ist mein erster Beitrag und ich hoffe, ich bin im
richtigen Unterforum gelandet. Bevor ich mich entschlossen habe dieses
Thema zu erstellen habe ich mir 10 Tage den Kopf zerbrochen und habe
sämtliche Suchmaschinen durchforstet ...
Kurz zu mir: Ihr dürft mich Helge nennen ;), ich bin 23 Jahre "alt",
komme aus dem schönen Ostfriesland und studiere Maschinenbau - nun im 5.
Semester, welches bei uns das Praxissemester ist - darum verbringe ich
ein halbes Jahr in München.
Zu meinem Projekt:
Ich bin zur Zeit dabei einen G-Code Interpreter zu programmieren (mit
den mitteln die mir zur Verfügung stehen) - darum darf mein
Programmierstil gerne kritisiert werden.
Achja, das ganze wird auf einem Arduino Mega 2560 umgesetzt.
Aktueller Stand ist, dass das ein- und auslesen des G-Codes von SD-Card
funktioniert, aufeinander treffende Geraden werden "übergeschliffen".
Die unterprogramme zum Verfahren von Geraden (Bresenham) und Kreisen
laufen ebenfalls.
Nun zum Problem:
Das beschleunigen der Achsantriebe. Als Motoren nutze ich aktuell noch
einfache Stepper - später sollen DC Servomotoren mit UHU Servocontroller
zum Einsatz kommen.
Nach ein wenig Recherche bin ich immer wieder auf das Prinzip von David
Austin gestoßen. Hier einer der vielen Links dazu:
http://www.embedded.com/design/mcus-processors-and-socs/4006438/Generate-stepper-motor-speed-profiles-in-real-time
Erstmal geht es mir nur um das anfahren des Motors. Dies funktioniert
auch, allerdings hat die erreichte Endgeschwindigkeit sowie die
Beschleunigungsdauer nichts mit den Werten zu tun, die ich vorgebe.
Leider weiss ich mittlerweile nicht mehr wo vorne und hinten ist.
Ich hänge nun mal einen knappen Code an - der eben ein schönes anlaufen
erzeugt, aber nicht so wie es die Solldaten vorgeben.
Am besten wäre wahrscheinlich, wenn sich jemand meldet, der genau dieses
vorgehen schon genutzt hat.
1 | // Timer variablen
|
2 | const long cpufreq = 16000000; // CPU Takt [Hz]
|
3 | const long f = 1000000; // Frequenz des Timers [Hz]
|
4 | const int prescaler = 1; // Timervorteiler
|
5 | int overf1; // Overflowvaribale Timer1 (Legt die Timerfrequenz fest)
|
6 |
|
7 | // Maschinendaten
|
8 | int p = 10; // Steigung der Spindel [mm]
|
9 | int res = 1600; // Steps pro Umdrehung, 1600 = 1/8 Betrieb
|
10 |
|
11 | // Bewegungsdaten
|
12 | double v_max = 60; // Endgeschwindigkeit [mm/s]
|
13 | double t = 2; // Beschleunigungszeit [s]
|
14 | double omega; // Winkelgeschwindigkeit [rad/s]
|
15 | double omega_d; // Winkelbeschleunigung [rad/s^2]
|
16 | double alpha; // Schrittwinkel pro Step [rad]
|
17 |
|
18 | // weitere Variablen
|
19 | const double pi = 3.141593; // pi
|
20 | long tn; // absoluter Zeitpunkt des Steps
|
21 | long i = 0; // Timeraufrufe seit letzten Step
|
22 | long n = 1; // aktueller Beschleunigungsstep
|
23 | long cnt0; // Zeit bis zum ersten Step
|
24 | long cntn; // Zeit zwischen letztem und nächstem Step
|
25 | long n_end; // zur Beschleunigung erforderliche Schritte
|
26 |
|
27 | void setup()
|
28 | {
|
29 | Serial.begin(115200);
|
30 | pinMode(13, OUTPUT);
|
31 |
|
32 | // maximale Winkelgeschwinigkeit
|
33 | omega = (v_max/p)*2*pi;
|
34 | // Winkelbeschleunigung
|
35 | omega_d = (omega/t);
|
36 | // Schrittwinkel pro Step
|
37 | alpha = (2*pi)/res;
|
38 | // erforderliche Steps bis maximale Geschwindigkeit
|
39 | n_end = ((omega*omega)/(2*alpha*omega_d));
|
40 |
|
41 | // Zeit bis zum ersten Step
|
42 | cnt0 = f * sqrt((2*alpha)/omega_d) * 0.676;
|
43 | cntn = cnt0;
|
44 |
|
45 | // absoluter Zeitpunkt des Steps
|
46 | // tn = sqrt((2*n*alpha)/omega_d);
|
47 |
|
48 | // Berechne Overflowvariable für Timer1
|
49 | overf1 = (cpufreq/(prescaler*f))-1;
|
50 | // Timer1 starten
|
51 | Timer1(overf1);
|
52 | }
|
53 |
|
54 | void Timer1(int overf1)
|
55 | {
|
56 | // initialize Timer1
|
57 | cli(); // disable global interrupts
|
58 | TCCR1A = 0; // set entire TCCR1A register to 0
|
59 | TCCR1B = 0; // same for TCCR1B
|
60 |
|
61 | // set compare match register to desired timer count:
|
62 | OCR1A = overf1;
|
63 | // turn on CTC mode:
|
64 | TCCR1B |= (1 << WGM12);
|
65 | // prescaler einstellen
|
66 | TCCR1B |= (1 << CS10);
|
67 | TCCR1B |= (0 << CS11);
|
68 | TCCR1B |= (0 << CS12);
|
69 | // enable timer compare interrupt:
|
70 | TIMSK1 |= (1 << OCIE1A);
|
71 |
|
72 | sei(); // enable global interrupts
|
73 | }
|
74 |
|
75 | ISR(TIMER1_COMPA_vect)
|
76 | {
|
77 | i++;
|
78 |
|
79 | if(i == cntn)
|
80 | {
|
81 | digitalWrite(13, HIGH);
|
82 |
|
83 | if(n < n_end)
|
84 | n++;
|
85 |
|
86 | //cntn = cntn - ((2*cntn)/(4*n+1));
|
87 | cntn = cnt0*(sqrt(n+1)-sqrt(n));
|
88 |
|
89 | i = 0;
|
90 |
|
91 | digitalWrite(13, LOW);
|
92 | }
|
93 | }
|
94 |
|
95 | void loop()
|
96 | {}
|
Es wäre klasse, wenn jemand Rat weiss oder andere Ideen ans Tageslicht
kommen. Weiterhin hoffe ich niemanden "erschlagen" zu haben :D
vielen Dank!
Helge