# Beschleunigungsrampe und Bremsrampe automatisch generieren



## Hektik (16. Dezember 2014)

Hallo Jungs! 

Ich bin seit ein paar Stunden am grübeln und komme irgendwie nicht auf einen vernünftigen Ansatz 

Ich habe einen Motor, den ich mit einer bestimmten Geschwindigkeit (Werte von 0-255) eine *bestimmte Zeit (in ms) *laufen lassen kann. Ich möchte aber, dass der Motor nicht direkt mit Endgeschwindigkeit losdüst, sondern wenigstens ansatzweise "beschleunigt" und "bremst", damit ich kein Problem mit den bewegten Massen bekomme.

Jetzt ist so eine Beschleunigungs- und Bremsrampe ja auch von der Höhe der Zielgeschwindigkeit abhängig und da ist bei mir irgendwie der Knoten 

Wenn ich einfach aufaddiere bis Endgeschwindigkeit, woher weiss ich denn dann, ab welchem Moment ich wieder anfangen muss, zu bremsen? Wenn ich die Zeit dynamisch in 3 Teile (beschleunigen, drehen, bremsen) teile, hab ich das Problem, das bei langen Laufzeiten auch lange beschleunigt wird, bei kurzen Laufzeiten wiederum wird entweder zu sehr beschleunigt oder die Endgeschwindigkeit nicht erreicht.

Weiß jemand Rat?

Gruß, 

Steffi


----------



## Bratkartoffel (16. Dezember 2014)

Hi,

Bremsen ist ja quasi negative Beschleunigung, von daher kannst du hier auch mit der "normalen" Beschleunigungsformel rechnen.
Ich denke es ist am sinnvollsten, wenn du für deinen Motor eine gewisse Beschleunigungsrate fix definierst, z.B. 2 m/s² ebenso für das Bremsen (z.B.: 3 m/s²)

Ich rechne jetzt einfach mal mit Sekunden, da ist das ganze anschaulicher:
- Der Motor startet zum Zeitpunkt t0 mit 0 m/s, er steht also still.
- Die Zielgeschwindigkeit ist 10 m/s. Von daher braucht er bei der obigen Beschleunigung 5 Sekunden bis er diese erreicht hat. (10 m/s   /  2 m/s² = 5s)
- Dann läuft er dort für 10 Sekunden und beginnt wieder zu bremsen
- Der Bremsvorgang dauert somit 10 / 3 = 3,33 Sekunden

Der gesamte Vorgang würde nach der obigen Rechnung also 5 + 10 + 3,33 Sekunden dauern, also 18,33 Sekunden.
Wenn du das ganze mit einer Geschwindigkeit von 12 m/s rechnest, dann kommst du auf 6 + 10 + 4 = 20 Sekunden.

Das ist jetzt ein sehr vereinfachter Fall mit linearer Beschleunigung. Mehr kannst du zum Beispiel auf Wikipedia darüber lesen.

// Edit: Wenn der Motor jetzt insgesamt nur 10 Sekunden laufen soll und die maximale Geschwindigkeit bis dahin ermitteln sollst, dann wirds schon etwas komplizierter. Welche Werte sind denn gegeben und welche Werte sollst du berechnen?

Grüße,
BK


----------



## ComFreek (16. Dezember 2014)

Bratkartoffel hat gesagt.:


> Das ist jetzt ein sehr vereinfachter Fall mit linearer Beschleunigung.


Du meinst wohl lineare Geschwindigkeit und konstante Beschleunigung, oder?

Ich würde einfach empfehlen, alle möglichen Parameter aufzulisten.
Das Geschwindigkeits-Zeit-Diagramm sieht wie folgt aus:

```
v ^
   |  /--------------------\
   | /                      \
   |/                        \
   -------------------------------------> t
   <T1><--------T2--------><T3>
```
T1: Zeitintervall für das Beschleunigungen.
T2: Zeitintervall für das Halten der Geschwindigkeit.
T3: Zeitintervall für das Bremsen (negative Beschleunigung).

a(1) bzw. a(2): Konstante Beschleunigung für das anfängliche Beschleunigen bzw. Bremsen.
a(max, 1): Maximale Beschleunigung für das anfängliche Beschleunigen.
a(max, 2): Maximale negative Beschleunigung für das Bremsen.



Hektik hat gesagt.:


> [...] hab ich das Problem, das[ s] bei langen Laufzeiten auch lange beschleunigt wird, bei kurzen Laufzeiten wiederum wird entweder zu sehr beschleunigt oder die Endgeschwindigkeit nicht erreicht.


1. Problem: Bei langen Laufzeiten wird T1 zu groß.
2. Problem: Bei kurzen Laufzeiten wird a(1) zu groß.

Lösung zu 1: Setze einen limitierenden Faktor und zwar a(max, 1).
Lösung zu 2: Dasselbe wie beim ersten Problem.

Wir kommen nun also auf dieselbe Lösung, die auch Bratkartoffel vorgeschlagen hat.


----------



## hela (16. Dezember 2014)

Hallo,
wenn es um die Steuerung von Schrittmotoren geht, dann ist u.U. auch die Limitierung der Geschwindigkeit notwendig. Das vom Motor aufzubringende Drehmoment wird bei großen Geschwindigkeiten kleiner und dann fehlt evtl. einfach die Kraft um weiter beschleunigen zu können. Das müsste man ggf. ausprobieren.

Siehe auch hier: *Beschleunigungsrampen richtig wählen und berechnen*


----------



## Hektik (16. Dezember 2014)

Hmm, ich glaub, ich hab mich falsch ausgedrückt  Also ich mach hier keine Hausaufgaben, sondern bastel ein wenig in der Werkstatt von meinem Freund mit einem Arduino herum. 
Also ich hab bereits eine funktionierende Funktion geschwindigkeit() und richtung() geschrieben, mit der ich bereits problemlos den Motor ansteuern kann. Geschwindigkeit() erwartet einen int von 0-255, Richtung braucht unsigned char mit "FWD" oder "RWD" für die Richtung.
Bei dem Motor handelt es sich um einen Gleichstrommotor (kein Stepper) der mithilfe einer provisorisch gebastelten H-Brücke die verschiedenen Geschwindigkeiten ermöglicht.

Ich habe hier auch schon zig Seiten Papier, mit eben jenen oben liebevoll in ASCII gezeichnetem Graphen liegen, verziert mit allerlei Denkarbeit, die nicht fruchtet.

Mein Problem liegt eher in der Umsetzung, nicht im Verständnis.

mal ein schnell getipptes Beispiel, wie mein Ansatz bisher ist:

```
v=200; //Geschwindigkeitsvorwahl von 200 (0-255 möglich)
richtung(FWD); // vorwärts drehen


geschwindigkeit(v); // Motor dreht mit v=200
warte(5000); // 5 sek lang
geschwindigkeit(0); // Motor anhalten

// Das war jetzt das Beispiel, wie ich den Motor 5 sek drehen lasse, jetzt die Beschleunigung, wie ich sie z.B. versucht habe:

for(i=0; i<=v; i++) {    // von 0 anfangen bis zum Wert von v addieren
    geschwindigkeit(i); // jeweils Geschwindigkeit setzen
    warte(5); // 5 ms Verzögerung pro "Stufe"
}
```

Wenn das jetzt aber 5 Sekunden drehen soll, muss ich ja auch vorher anfangen zu bremsen und da is irgendwie... der Knoten... :/


----------



## hela (16. Dezember 2014)

Wenn du die Schleife von 1 bis 200 durchlaufen lässt, dann beschleunigt dein Motor von Null auf 200 in 1000 ms. So lange dauert also die pos. Beschleunigung.
Wenn du die Schleife von 200 bis 0 durchlaufen lässt, dann dauert deine Bremsrampe ebenfalls 1000 ms.
... Weiter wie in ComFreeks Beitrag ;o)


----------



## ComFreek (16. Dezember 2014)

hela hat gesagt.:


> Wenn du die Schleife von 1 bis 200 durchlaufen lässt, dann beschleunigt dein Motor von Null auf 200 in 1000 ms. So lange dauert also die pos. Beschleunigung.


Genau, du hast also eine Beschleunigung von 200 m/s^2 (sofern v in m/s gehandhabt wird).

Wegen der gleichmäßig beschleunigten Bewegung haben wir:

```
a = const.
v = a * t

// Mit Hilfe unserer angestrebten Geschwindigkeit
v = v_max
// Benötigte Zeit, um Geschwindigkeit v mit Beschleunigung a zu erreichen
=> t_max = v_max/a
```

Deswegen:

```
// Wir wollen auf 200 m/s beschleunigen
const int V_MAX = 200;
// Mit einer Maximalbeschleunigung von 200 m/s^2
const int A_MAX = 200;

int tMax = (V_MAX / a) * 1000;
const int DELTA_T = 10; // 10ms Steps
for (int t=0; t <= tMax; t += DELTA_T) {
  geschwindigkeit(A_MAX * t);
  warte(DELTA_T);
}
// Falls tMax nicht restlos durch DELTA_T teilbar:
// Geschwindigkeit auf V_MAX setzen
// Der größtmögliche Sprung ist hierbei (DELTA_T - 1)
geschwindigkeit(V_MAX)
```


----------



## ikosaeder (17. Dezember 2014)

Ich stimmte Bratkartoffel zu. Ich würde es so formulieren: Du zerlegst deine Gesamtzeit in eine Anzahl gleichgroßer Intervalle (Zeitschritte mit fester Zeitschrittweite). Dann kannst du eine Beschleunigungrampe definieren, die die Geschwindigkeit solange erhöht, bis die Maximale Geschwindigkeit erreicht ist.
Die Rate legst du fest, wie Bratkartoffel schon geschrieben hat. Genauso legst du für den Bremsvorgang eine Rate fest. Aus der Maximalen Geschwindigkeit, der Bremsrate und der Zeitschrittweite kannst du berechnen wieviele Zeitschritte du brauchst um von der Endgeschwindigkeit wieder auf 0 abzubremsen. 
Das ganze könnte man etwa so programmieren:

```
float vel # Aktuelle Geschwindigkeit
float max_vel # Endgeschwindigkeit
float # Gesamtzeit
int n # Zeitschritt
int n_max # Max Zeitritt
float a # Anfahrtbeschleunigung
float b # Bremsbeschleunigung
float dt
int ndtb
dt=t/n_max #Zeitschrittweite
ndtb=max_vel/b/dt #Zeitschritte um von max_vel auf 0 zu kommen

for {n=1;n<n_max;n++}
  if (n<(n_max - ndtb)){  
    if(vel<max_vel) {
       #Beschleunigungsrampe
       vel=vel+a*dt
    }
    else{
      vel=max_vel
    }
  }
  else{
    #Bremsrampe
    vel=vel-b*dt
  }
vel=0
```
Die Dauer der Beschleunigung und des Bremsvorgangs ist nicht von der Laufzeit abhängig, sondern nur von der Endgeschwindigkeit. Das heißt lange Laufzeiten sind kein Problem.
Aber, wie du selbst gesagt hast, es wird problematisch, wenn nicht genug Zeitschritte/Zeit zur Verfügung stehen. Du brauchst also eine gewisse Mindestlaufzeit um die Endgeschwindigkeit zu erreichen.


----------

