Frage zur Taktgenerierung per Arduino

Hallo liebe Forengemeinde !

Als absoluter Noob stehe ich vor einem Problem bei dem Ihr mir sicher helfen könnt.

Ich benötige für eine Astrokameranachführung per Getriebe, Untersetzung und Steppermotor einen
Taktgenerator welcher einen Takt bis auf 3 Nachkommastellen erzeugt.

Nun zur eigentlichen Frage :

Muss ich beim Takt der als Bsp. alle 300ms für 50ms anliegt das Timing auf 300ms setzen oder
die Taktdauer abziehen, so dass ich das Timing auf 250ms setzen muss?

Danke im Voraus für eure Antworten

Com75:
Ich benötige für eine Astrokameranachführung per Getriebe, Untersetzung und Steppermotor einen
Taktgenerator welcher einen Takt bis auf 3 Nachkommastellen erzeugt.

Drei Nachkommastellen bei was? Jahre? Monate? Tage? Stunden? Minuten? Sekunden?

Der Arduino hat zwei Funktionen millis() und micros() mit denen er Dir einen Milli- und Mikrosekundentakt frei Entwicklungsumgebung liefert.

Allerdings ist der Takt vom 16 MHz Systemtakt abgeleitet und daher absolut gesehen nicht besonders genau.

Kannst Du es etwas detaillierter beschreiben, was Du genau brauchst?

Com75:
Nun zur eigentlichen Frage :
Muss ich beim Takt der als Bsp. alle 300ms für 50ms anliegt das Timing auf 300ms setzen oder
die Taktdauer abziehen, so dass ich das Timing auf 250ms setzen muss?

Wenn Du alle x Millisekunden einen Schritt machen mußt, muß natürlich die Periode des Ansteuerungssignals x mS lang sein, nicht nur der HIGH oder LOW-Teil.

Je nach Schrittmotortreiber kann der Schrittimpiuls sehr kurz sein. Genaueres im Datenblatt des verwendeten Treibers.

Grüße Uwe

Also um etws konkreter zu werden stelle ich euch kurz mein Projekt vor.

Es geht um eine Nachführung für eine Astrokamera. Diese soll sich, um die Erdrotation auszugleichen, mit der gleichen
Winkelgeschwindigkeit wie die Erde drehen. Diese dreht sich in 24H um 360°. Das entspricht 0,00417807416313755° pro Sekunde.
Der Steppermotor hat pro Schritt einen Drehwinkel von 1,8°. Das bedeutet also das 430,8 -fache von dem was er drehen sollte.
Mit einem Getriebe mit der Untersetzung von 1:43 und 16 Microstepps pro Schritt muss der Schrittmotor alle 0,626192587209302
Sekunden (f=1,59695279124369/s) um einen Schritt weiterfahren. Daher die Genauigkeit von von 3 Nachkommastellen.

Die Frage ist nun, wenn ich alle 626 Millisekunden ein Signal zum Steppertreiber (A4988) mit der Dauer von 50ms schicke, muss ich den Takt dann so programmieren, dass er alle 626 Millisekunden für 50ms wiederholt wird oder alle 576ms für 50ms ?

Also:

pin(x) high
delay 50ms

alle 626ms oder 567ms

Wie Ihr seht hat das bei der beabsichtigten Genauigkeit eine entscheidende Bedeutung....

Com75:
Die Frage ist nun, wenn ich alle 626 Millisekunden ein Signal zum Steppertreiber (A4988) mit der Dauer von 50ms schicke, muss ich den Takt dann so programmieren, dass er alle 626 Millisekunden für 50ms wiederholt wird oder alle 576ms für 50ms ?

Mal kurz in die Beschreibung des Stepper-Treibers reingeschaut und gelesen:
Each pulse to the STEP input corresponds to one microstep of the stepper motor

Unter "pulse" versteht man typischerweise 1HIGH und 1LOW = 1 pulse

Also mußt Du alle 626 ms den Ausgang einmal für eine gewisse Zeit HIGH setzen.

Com75:
Der Steppermotor hat pro Schritt einen Drehwinkel von 1,8°. Das bedeutet also das 430,8 -fache von dem was er drehen sollte.
Mit einem Getriebe mit der Untersetzung von 1:43 und 16 Microstepps pro Schritt muss der Schrittmotor alle 0,626192587209302
Sekunden (f=1,59695279124369/s) um einen Schritt weiterfahren. Daher die Genauigkeit von von 3 Nachkommastellen.

Hallo,

wenn ich das richtig verstehe, würde das bedeuten, dass die Kamera direkt an den Stepper bzw. das Getriebe montiert ist. Aber in der Regel macht man das nicht so. Angenommen, Du hast eine Schottische Montierung (Barndoor mit Motor), Dein Stepper hat einen Schrittwinkel von 1,8°, eine Mutter wird vom Stepper angetrieben und schraubt eine Gewindestange durch, diese bewegt die Kamera-Montierung. Die Gewindestange hat eine Steigung von 1 mm pro Umdrehung.

Dann würdest Du 200 Schritte pro Minute brauchen. Du musst also alle 0,3s einen Schritt auslösen.

Da die Programmzeilen rund um das Auslösen des Schrittes und die Erzeugung der nötigen Wartezeit zwischen den Schritten auch Zeit brauchen, würde ich so vorgehen: Eine Markierung auf der Motorachse anbringen, eine Markierung daneben anbringen. Die beiden Markierungen deckungsgleich ausrichten. Folgenden Pseudocode am Anfang verwenden:

for(int i=0; i<200; i++) {
  // Schritt auslösen
  delay(330);
}

Wenn das läuft sollte der Motor losdrehen und am Ende wieder stehenbleiben, wenn die Markierungen wieder deckungsgleich sind. Die Zeit dafür misst Du mit einer Stoppuhr. Ist sie kürzer als 60 Sekunden, erhöhst Du die Zahl im delay(); , ist sie länger, erniedrigst Du die Zahl im delay(); .

Sollte Dir das noch nicht genau genug sein, könntest Du folgender Maßen weitermachen:

for(int i=0; i<200; i++) {
  // Schritt auslösen
  delay(329);
  delayMicroseconds(200);
}

Diese Art der Zeiteinstellung kannst Du sicherlich auch mit Deiner Montierung verwenden. Hoffe, meine Idee ist verständlich rüber gekommen.

Gruß,
Ralf

Erstmal ein herzliches Dankeschön für Eure Antworten :smiley:

Leider verstehe ich immer noch nicht wie es funktioniert.... :0

Wenn ich alle 626ms den pin (x) high setze, dann 50ms warte und anschließend auf low setze, dann ergibt sich doch eine
Gesammtdauer von 676ms, oder zählt der Arduino intern weiter und der high/low Wechsel mit 50ms delay wird nicht
mitgezählt ?

Ich meine das die Zeitdifferenz von 9% ganz schön enorm ist, von daher ist die Frage also nicht unberechtigt.....

Grüße Com75 (totally confused...)

@Ralf: Die Idee mit der Barndoor ist zwar ganz nett, allerdings ergibt sich da mit der Zeit ein GANZ übler Tangentialfehler.
daher möchte ich das ganze ja mit einer sich drehenden Plattform machen....

Com75:
Wenn ich alle 626ms den pin (x) high setze, dann 50ms warte und anschließend auf low setze, dann ergibt sich doch eine
Gesammtdauer von 676ms, oder zählt der Arduino intern weiter und der high/low Wechsel mit 50ms delay wird nicht
mitgezählt ?

Sowohl der millis() als auch der micros() Zeitzähler zählen auf dem Arduino die Zeit weiter, während ein delay läuft.

D.h. wenn Du "alle 626ms" etwas startest, dann läuft auch "alle 626ms" etwas ab.

Damit etwas wirklich exakt im vorgegebenen Takt abläuft, auch wenn zwischendurch noch anderer Code ausgeführt wird, müßtest Du eben den Impuls jedesmal dann ausgeben, wenn der Millis-Zähler entsprechend vorgelaufen ist.

Beispielcode dafür, um etwas immer im vorgegebenen Zeitabstand auszuführen:

#define MOTOR 13

void setup() {
  Serial.begin(9600);
  pinMode(MOTOR,OUTPUT);
}

#define TICKTIME 626

boolean oneTick(){
  // testet, ob die TICKTIME vergangen ist
  static unsigned long prevMillis;
  boolean result=false;
  if ( millis() - prevMillis >= TICKTIME) 
  {      
    result=true;
    prevMillis += TICKTIME;	
  }
  return result;
}


void loop() {
  if (oneTick())
  {
    digitalWrite(MOTOR,HIGH);
    delay(50);
    digitalWrite(MOTOR,LOW);
  }
}

Millisekunden ist allerdings eine recht grobe Teilung. Wenn Du bessere Möglichkeiten zur Feineinstellung haben möchtest, z.B. um Taktfrequenzunterschiede von Arduino-Boards ohne Schwingquarz sondern mit ungenauen Resonatoren etwas auszugleichen, kannst Du die TICKTIME auch in Mikrosekunden vorgeben und in der oneTick()-Funktion micros() statt millis() verwenden.

Com75:
Also:
pin(x) high
delay 50ms
alle 626ms oder 567ms

Hallo,

dass mit der Barndoor war ja nur ein Beispiel. Ich glaube aber, ich habe Deine Idee jetzt besser verstanden, also nochmal Pseudocode:

void loop() {
  schrittAusloesen();
  delay(577);
}

void schrittAusloesen() {
  // Signal an den Motortreiber schicken
  delay(50);
}

Aber damit wirst Du auch nicht auf eine Rate von 627ms kommen, denn der Aufruf der Funktion und die Abarbeitung der Anweisungen benötigt auch Zeit. delay(577); wird also etwas zu groß sein. Hier müsstest Du das System wirklich eine festgesetzte Zeit (ich denke in Deinem Fall 24 Stunden) laufen lassen und die 577 dann entsprechend anpassen. Das kann natürlich ein paar Tage dauern :frowning:

Ansonsten würde mir noch einfallen, das Timing mit einem Oszilloskop zu messen und zu schauen, ob wirklich alle 627ms ein Schritt erfolgt.

Bedenken solltest Du auch, das wahrscheinlich eine gewisse Anzahl von Zyklen vom Interrupt des Arduino getroffen werden. Dadurch geht Dir zwar keine Wartezeit "verloren", aber der Schritt wird später (nach Abarbeitung der ISR) nachgeholt. Falls Du eine hinlänglich genaue Messmöglichkeit für Winkel hast, könntest Du das System z.B. eine Stunde laufen lassen (falls meine Annahme mit den 24 Stunden stimmt) und dann messen, ob 15° weiter gedreht wurde.

Gruß,
Ralf

Hallo,
"16 MHz Systemtakt abgeleitet und daher absolut gesehen nicht besonders genau."

Wenn Du einen "genauen" Takt brauchst, dann hole ihn Dir doch von einer RTC.
Es gibt Module (z.B. ChronoDot) die liefern Dir an einem bestimmten Ausgang
einen "hochgenauen" Takt.

Der Arduino rechnet immer mit voller Genauigkeit, wenn Du auf drei Stellen
kommen willst, dann mußt Du die extra- "runden".

Das TaktSignal der RTC würde Dir auch die "ungenaue" Rechnerei mit millis()
ersparen.

"Drehwinkel von 1,8°" das würde ich mir überlegen. Der wäre mir für diese
Anwendung zu groß. Das kommt zwar bei Radius 0 (null) hin, aber wo liegst
Du bei Radius 412Km ? Wenn Du z.B. die ISS knipsen willst.
Gruß und Spaß
Andreas

Schachmann:
Aber damit wirst Du auch nicht auf eine Rate von 627ms kommen, denn der Aufruf der Funktion und die Abarbeitung der Anweisungen benötigt auch Zeit.

Genau deshalb habe ich in Reply #7 ja auch einen Code gepostet, der seinen Takt einhält und nicht abhängig ist, ob der Code zwischendurch ein paar Millisekunden mehr oder weniger läuft.

Ihr seid Spitze, vielen Dank !!!!

Mir hat es schlicht am Verständnis gefehlt, ob der interne Timer weiter läuft bei einem Delay oder nicht.

Aber anhand der Codeschnipsel / Bsp. wird das Problem sicher lösbar sein.

LG Com75

Ps. Sind keine 1,8° pro schritt sondern 1,8° / (43*16) = 0,0026 ° pro Step. Ich denke das wird genau genug sein....

jurs:
Genau deshalb habe ich in Reply #7 ja auch einen Code gepostet, der seinen Takt einhält und nicht abhängig ist, ob der Code zwischendurch ein paar Millisekunden mehr oder weniger läuft.

Kam während ich am Schreiben war, hatte ich übersehen. Ist sicherlich besser als mein Vorschlag.

Gruß,
Ralf

Hallo,
wenn Dein Datenblatt des Motor per Impuls 1,8° angibt, dann ist das so.
Bei einem halben Impuls macht der nichts. Also nichts mit MikroStep.
Kompensieren möchtest Du das über ein Getriebe (wie immer das funktionieren sollte)

Ich selbst bin Zerspanungsmechaniker, Fachrichtung Fräsen.

"0,0026 ° pro Step. Ich denke das wird genau genug sein…."

Das halte ich für ziemlich sportlich- Du kannst dankbar sein, wenn Du ein Grad
schaffst, mit einer Wiederholgenauigkeit von 0,5 Grad.
Gruß und Spaß
Andreas

@ SkobyMobil

Du hast schon recht, der Motor macht 200 Steps pro Drehung. Daraus ergibt sich ein Schrittwinkel von 1,8°.
Allerdings ist der Motor angeblich Microstep-fähig. Das Microstepping liefert der A4988 mit 1/2 , 1/4 , 1/8 oder eben 1/16
Schritten. Der Motor kann also statt 200 Steps pro Umdrehung mit 3200 Steps pro Umdrehung angesteuert werden.
Ein nachgelagertes Getriebe mit der Untersetzung von 43:1 soll sich um den Rest kümmern. Soviel zur Theorie. In der Praxis
werden Astromontierungen ala Vixen Polarie genauso angetrieben...(statt Getrieb halt Schneckenrad) siehe:


Sollte also funtionieren, oder

Hallo,
das nenne ich ja mal Antrieb. Hast Du einen "KaufDatenblattLink" ?
Wenn Du den Antrieb mit einer "Schnecke" realisierst, kommst Du der Sache schon etwas näher.
Gruß und Dank
Andreas

Na ich dachte :sowas kann man ja auch selber machen ohne dafür 500.-€ oder mehr auszugeben.
Zumal ich das Planetengetriebe ja für "lau" bekommen habe.. 8)

Aber was meintest Du mit "KaufDatenblattLink" ?????

Com75:
Mir hat es schlicht am Verständnis gefehlt, ob der interne Timer weiter läuft bei einem Delay oder nicht.

Delay hält nicht den Prozessor komplett an. Das macht lediglich busy waiting bis Timer0 entsprechend weitergelaufen ist.

Hallo,
ich habe den Motor gesucht, nach der Nummer auf dem Foto.
KaufLink- was kostet der, wo gibt es ihn
DatenblattLink- was kann er, wie ansteuern, technische Daten.
Gruß und Dank
Andreas

Ach so !

Das Ding auf dem Foto heißt: Vixen Polarie, einfach mal googlen.

Falls das nicht gemeint war : Steppertreiber ist ein A4988 von pololu für arduino, der stepper den ich habe: "Ebay second hand"
Getriebe ist von GEZE Stellmotor E205 von mir umgerüstet auf Stepper anstatt Synchonmotor.

Ich poste mal Fotos wenn das Projekt vorangeschritten ist....