Forum: Mikrocontroller und Digitale Elektronik Schrittmotoransteuerung für "Seismograph"


von hansi (Gast)


Lesenswert?

Hallo zusammen,

ich versuche im Moment eine Art "Seismograph" für Audiosignale zu 
basteln. An einer Führungsschiene hängt ein Schlitten mit einem Stift, 
der von einem Schrittmotor über einen rudimentären Seilzug auf und ab 
gefahren werden kann.

Es funktioniert auch ganz gut, leider nur sehr langsam. Sobald ich 
versuche den Motor schneller anzufahren, dreht er durch. Auch beim 
Richtungswechsel scheint er einige Schritte zu verlieren…

Man muss den Motor wohl mit einer "Rampe" anfahren, um die maximale 
Geschwindigkeit erreichen zu können. Viele Beispiele, die ich dazu im 
Netz gefunden habe, beziehen sich aber leider auf Anwendungen, bei denen 
der Motor zu einer bestimmten Position fahren soll, dann zur Nächsten, 
dann zur Nächsten…

In meinem Fall habe ich ja ein Echtzeit-Signal durch ein Mikrofon am 
ADC. Ich muss also irgendwie dynamisch eine Rampe hinbekommen, die z.B. 
bei jedem Richtungswechsel erfolgt.

Das ganze läuft bei mit mit einem Schrittmotor, über einen Sparkfun 
EasyDriver (Allegro 3967) an einem Arduino Uno (atmega328p). Der Treiber 
bekommt ein 50%-Duty-Cycle PWM für die Steps, Geschwindigkeit lässt sich 
über die Periode regeln.
1
  Timer1.initialize();
2
  Timer1.attachInterrupt(save_step); //position speichern
3
  Timer1.setPeriod(400);
1
void save_step(){
2
 steps += ( digitalRead(V_DIR_PIN) == HIGH) ? 1 : -1;
3
}

Mein erster Ansatz ist es, in der save_step() die Rampe einzubauen: Bei 
einem Richtungswechsel wird eine Variable ramp_step auf 0 gesetzt:
1
void save_step(){
2
 if( ramp_step < 10 ){
3
  Timer1.setPeriod(ramp_values[ramp_step]);
4
  ramp_step++;
5
 }
6
7
 steps += ( digitalRead(V_DIR_PIN) == HIGH) ? 1 : -1;
8
}

Das funktioniert auch soweit, aber doch nicht so richtig gut. Bzw. weiss 
ich nicht, was die optimalen Werte für meinen Motor (Oriental PK243, 
Leihgabe von einem Freund) sind.

Jemand noch Vorschläge, Tipps, etc?

Vielen Dank

von Jack (Gast)


Lesenswert?

Vielleicht ist ein (Schritt)motor nicht das richtige dafür?

Willst du die Audio-Waveform in Echtzeit in grossen Dimensionen 
aufzeichnen? Dann muss der Schreibkopf extrem leicht sein um die 
schnellen Richtungswechsel mitzumachen. Als "Antrieb" würde ich eher was 
mit Magnet / Spule versuchen, ähnlich wie ein Lautsprecher, aber anstatt 
einer Membrane wird ein Stift bewegt. Aber bei Frequenzen bis 20000 Hz 
wirds wohl ziemlich unmöglich...

von Klaus D. (kolisson)


Lesenswert?

Vielleicht wäre der Antrieb eines Festplattenlesekopfes das richtige.

Klaus

von Uwe (Gast)


Lesenswert?

> Vielleicht wäre der Antrieb eines Festplattenlesekopfes das richtige.

Jup würde ich auch sagen kannste auch nen normalen 
Lautsprecherverstärker zum Treiben nehmen. Mußt natürlich auf die 
Impedanz achten.

von hansi (Gast)


Angehängte Dateien:

Lesenswert?

Der Lesekopf von der Festplatte wäre bestimmt perfekt, aber das ganze 
soll ziemlich groß werden (Auschläge bis zu ca 20cm).

Ich habe heute weitergearbeitet und folgendes versucht: Kein 
Hardware-PWM mehr auf den Ausgangspin schicken, stattdessen wird im 
Interrupt der Pin HIGH und LOW gezogen:
1
void save_step(){
2
3
 digitalWrite(V_STEP_PIN, HIGH);
4
 delayMicroseconds(2); 
5
 digitalWrite(V_STEP_PIN, LOW);
6
 
7
 if(ramp_step < RAMP_STEPS){
8
   Timer1.setPeriod(ramp_steps[ramp_step]);
9
   ramp_step++;
10
   for(int i=0; i<30000; i++){
11
     //do nothing
12
   }
13
 }
14
   
15
 v_step += ( digitalRead(V_DIR_PIN) == HIGH) ? 1 : -1;
16
17
}

Schneller wurde es dadurch nicht, aber es fühlt sich so "besser" an, als 
mit dem Hardware PWM auf 50% cycle…?

Problem hier: Reichen 100 Steps für die Rampe? Wieviel Pause muss 
zwischen den Steps sein, damit die Rampe wirklich effektiv ist? (Hier 
mal ein versuch mit for(i<30000) um ein bisschen delay zu erzeugen.)

Die Werte für die Rampe werden übrigens am Anfang des Programms 
berechnet und in ein Array geschrieben:
1
  
2
#define RAMP_STEPS 100
3
#define RAMP_BETA .06551080335043f // = ln(speed_min - speed_max + 1)/RAMP_STEPS)
4
#define RAMP_E 2.71828182845904f
5
for(int x=0; x<RAMP_STEPS; x++){
6
    ramp_steps[i] = RAMP_START + 1 - pow(RAMP_E, RAMP_BETA * x);
7
  }

Das ist eine frei erfundene Kurve, fällt von 800us erst flach… dann 
immer steiler auf 200 ab. (Bei 200us Takt zwischen den Steps scheint 
– in meinem Programm – das Maximum für meinen Motor zu liegen…)

Gibt es eine "Idealkurve"? Wie kann ich die bestimmen?

Ausserdem hänge ich ein bisschen an dem generellen Problem, wie man das 
Audiosignal am besten aufbereitet. Das was am AIN ankommt, habe ich mal 
als Anhang beigefügt (10. Gibt es vielleicht ein paar Tricks, wie man 
sowas am besten in einen "trägen Zeiger" umsetzt, weil der Stepper kann 
ja in keinem Fall so schnell wie z.B. ein Drehspulinstrument oder eine 
LED-Leiste auf die Ton-Impulse reagieren.

Vielen Dank für eure Vorschläge!

Schönen Abend

Hans

von Tom (Gast)


Lesenswert?

hansi schrieb:
> Wieviel Pause muss
> zwischen den Steps sein, damit die Rampe wirklich effektiv ist?

Die Pausendauer ist nicht das Kriterium. Die Kräfte dürfen einen 
bestimmten Wert nicht überschreiten, d.h. die Beschleunigung muß 
begrenzt werden. Daraus ergibt sie dann eine Bedingung für das 
Geschwindigkeitsprofil und die Schrittzeit.
Dazu steht z.B. in der App. Note 446 von Atmel einiges.
http://www.atmel.com/dyn/resources/prod_documents/AVR446.zip

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.