Schrittmotor Uhr

Hallo an alle!

Ich möchte gerne eine Uhr bauen, die mit zwei kleinen Schrittmotoren und einem Arduino Uno gesteuert wird.
Dazu habe ich mir zwei 28BYJ-48 Schrittmotoren gekauft ( die für ein paar Euro).

Folgendes Problem:
Ein Motor soll sich konstant mit einer Geschwindigkeit drehen (z.b. eine Umdrehung pro 60 Minuten)
der andere Motor soll still stehen und sich jede Stunde um X Schritte drehen. Der eine Motor zeigt die aktuelle Stunde an, der andere läuft mit den Minuten. Schonmal vorweg, es brauch nicht super genau sein.

Der Motor der sich konstant drehen soll ist bereits am laufen. Aber wie bekomme ich den zweiten zeitgleich zum laufen?! Habe es mit Delay() versucht aber dann steht ja das Programm still. Auch das mit dem Blinken ohne Delay funktioniert nicht so richtig.

Ich würde mich freuen wenn mir jemand helfen kann.

int motorPin1 = 8; // Blue - In 1
int motorPin2 = 9; // Pink - In 2
int motorPin3 = 10; // Yellow - In 3
int motorPin4 = 11; // Orange - In 4

int motorSpeed = 100;

void setup() {
pinMode(motorPin1, OUTPUT);
pinMode(motorPin2, OUTPUT);
pinMode(motorPin3, OUTPUT);
pinMode(motorPin4, OUTPUT);
}

void loop()
{ // 1
digitalWrite(motorPin4, HIGH);
digitalWrite(motorPin3, LOW);
digitalWrite(motorPin2, LOW);
digitalWrite(motorPin1, LOW);
delay(motorSpeed);

// 2
digitalWrite(motorPin4, HIGH);
digitalWrite(motorPin3, HIGH);
digitalWrite(motorPin2, LOW);
digitalWrite(motorPin1, LOW);
delay(motorSpeed);

// 3
digitalWrite(motorPin4, LOW);
digitalWrite(motorPin3, HIGH);
digitalWrite(motorPin2, LOW);
digitalWrite(motorPin1, LOW);
delay(motorSpeed);

// 4
digitalWrite(motorPin4, LOW);
digitalWrite(motorPin3, HIGH);
digitalWrite(motorPin2, HIGH);
digitalWrite(motorPin1, LOW);
delay(motorSpeed);

// 5
digitalWrite(motorPin4, LOW);
digitalWrite(motorPin3, LOW);
digitalWrite(motorPin2, HIGH);
digitalWrite(motorPin1, LOW);
delay(motorSpeed);

// 6
digitalWrite(motorPin4, LOW);
digitalWrite(motorPin3, LOW);
digitalWrite(motorPin2, HIGH);
digitalWrite(motorPin1, HIGH);
delay(motorSpeed);

// 7
digitalWrite(motorPin4, LOW);
digitalWrite(motorPin3, LOW);
digitalWrite(motorPin2, LOW);
digitalWrite(motorPin1, HIGH);
delay(motorSpeed);

// 8
digitalWrite(motorPin4, HIGH);
digitalWrite(motorPin3, LOW);
digitalWrite(motorPin2, LOW);
digitalWrite(motorPin1, HIGH);
delay(motorSpeed);
}

So auf jedenfall nicht, wo ist dein Versuch mit BlinkWithoutDelay?

Muno:
Folgendes Problem:
Ein Motor soll sich konstant mit einer Geschwindigkeit drehen (z.b. eine Umdrehung pro 60 Minuten)
der andere Motor soll still stehen und sich jede Stunde um X Schritte drehen. Der eine Motor zeigt die aktuelle Stunde an, der andere läuft mit den Minuten. Schonmal vorweg, es brauch nicht super genau sein.

Wo ist das Problem? Der eine Motor dreht sich also 12mal so schnell wie der andere? Der Stundenzeiger macht 24 Umdrehungen pro Tag, der Stundenzeiger nur 2 Umrehungen pro Tag.

Muno:
Der Motor der sich konstant drehen soll ist bereits am laufen. Aber wie bekomme ich den zweiten zeitgleich zum laufen?!

Du zählst einfach ab, wie viele Schritte Du mit dem einen Motor machst: Nachdem der Motor für den Minutenzeiger 12 Schritte gemacht hast, machst Du immer genau einen Schritt mit dem Stundenzeiger.

Um die Programmlogik einfach zu halten, würde ich einfach die 8 Schritte, die Du momentan in der loop-Funktion ausführst, zu einem einzigen Schritt zusammenfassen, zum Beispiel in einer "stepper1()" Funktion.

Dann mußt Du Dir nur noch ausrechnen, alle wie viele Mikrosekunden Du diese Schrittfunktion aufrufen mußt, ich bin mal ausgegangen von:

const long stepMicros=109863L; // Anzahl Microsekunden zwischen zwei Schritten

Und nach je 12 Aufrufen dieser Funktion mußt Du dann eine zweite Funktion 'stepper2();' aufrufen, die den zweiten Schrittmotor dann mit genau 1/12 der Drehzahl des ersten Motors bewegt.

Grobes Programmgrundgerüst etwa:

int motorPin1 = 8;  // Blue   - In 1
int motorPin2 = 9;  // Pink   - In 2
int motorPin3 = 10; // Yellow - In 3
int motorPin4 = 11; // Orange - In 4
                         
int stepperSpeed = 1600; // Minimum Anzahl Mikrosekunden zwischen  zwei Steps

void setup() {
  pinMode(motorPin1, OUTPUT);
  pinMode(motorPin2, OUTPUT);
  pinMode(motorPin3, OUTPUT);
  pinMode(motorPin4, OUTPUT);
}

void stepper1()
  { // 1
  digitalWrite(motorPin4, HIGH);
  digitalWrite(motorPin3, LOW);
  digitalWrite(motorPin2, LOW);
  digitalWrite(motorPin1, LOW);
  delayMicroseconds(stepperSpeed);

  // 2
  digitalWrite(motorPin4, HIGH);
  digitalWrite(motorPin3, HIGH);
  digitalWrite(motorPin2, LOW);
  digitalWrite(motorPin1, LOW);
  delayMicroseconds(stepperSpeed);


  // 3
  digitalWrite(motorPin4, LOW);
  digitalWrite(motorPin3, HIGH);
  digitalWrite(motorPin2, LOW);
  digitalWrite(motorPin1, LOW);
  delayMicroseconds(stepperSpeed);


  // 4
  digitalWrite(motorPin4, LOW);
  digitalWrite(motorPin3, HIGH);
  digitalWrite(motorPin2, HIGH);
  digitalWrite(motorPin1, LOW);
  delayMicroseconds(stepperSpeed);


  // 5
  digitalWrite(motorPin4, LOW);
  digitalWrite(motorPin3, LOW);
  digitalWrite(motorPin2, HIGH);
  digitalWrite(motorPin1, LOW);
  delayMicroseconds(stepperSpeed);


  // 6
  digitalWrite(motorPin4, LOW);
  digitalWrite(motorPin3, LOW);
  digitalWrite(motorPin2, HIGH);
  digitalWrite(motorPin1, HIGH);
  delayMicroseconds(stepperSpeed);


  // 7
  digitalWrite(motorPin4, LOW);
  digitalWrite(motorPin3, LOW);
  digitalWrite(motorPin2, LOW);
  digitalWrite(motorPin1, HIGH);
  delayMicroseconds(stepperSpeed);


  // 8
  digitalWrite(motorPin4, HIGH);
  digitalWrite(motorPin3, LOW);
  digitalWrite(motorPin2, LOW);
  digitalWrite(motorPin1, HIGH);
  delayMicroseconds(stepperSpeed);
}

void stepper2()
{
}


unsigned long lastStepMicros;
const long stepMicros=109863L; // Anzahl Microsekunden zwischen zwei Schritten
int count;
void loop()
{
  if (micros()-lastStepMicros>=stepMicros) // Schrittdauer ist um, mache einen Schritt
  {
     stepper1();
     lastStepMicros+=stepMicros; // Zeit weiterzählen
     count++;  // Schrittzähler weiterzählen
     if (count>=12) // Nach je 12 Schritten, mache einen Schritt mit dem zweiten Motor
     {
       stepper2();
       count=0;
     }
  }
}

Über die Variable 'stepMicros' legst Du dann fest, wie schnell die Uhrenmotoren tatsächlich laufen. Je kleiner die Anzahl der Mikrosekunden pro Schritt, desto schneller läuft die Uhr.

Mit einer Gangabweichung von mehreren Minuten pro Tag ist bei einer solchen Uhrzeitanzeige, die vom 16 MHz Takt des Controllers abgeleitet wird, zu rechnen. Für eine genauer gehende Uhr mußt Du die Zeit von einem RTC-Modul ("Realtime Clock") ableiten.

Hallo und willkommen im Forum!

Leider kann ich nicht so toll programmieren wie jurs, aber bei meiner Anleitung Ein Endlicher Automat entsteht habe ich genau so einen Motor für mein Kohlekranmodell verwendet. Möglicherweise findest Du dort eine für Dich sinnvolle Anregung.

Vielen Dank!

Dein Programm Jurs ist wirklich prima, vielen Dank dafür. Mit meinen Arduino Basics komme ich noch nicht so weit.
Am Ende des Programms soll Stepper2 ja eine Umdrehung machen, also ca.4000 Steps.
Wie löse ich das am besten? Ich habe stepper2() 4000 mal kopiert, das ging :smiley:
Wenn der Arduino wirklich so eine Zeitabweichung hat, wäre es vielleicht doch sinnvoll eine RTC zu benutzen. Ist das mit einigermaßen überschaubarem Umfang machbar oder sollte ich das Projekt lieber bei Seite legen?

So sieht das Programm jetzt aus:

int motorPin1 = 8; // Blue - In 1
int motorPin2 = 9; // Pink - In 2
int motorPin3 = 10; // Yellow - In 3
int motorPin4 = 11; // Orange - In 4

int motorPin5 = 2; // Blue - In 1
int motorPin6 = 3; // Pink - In 2
int motorPin7 = 4; // Yellow - In 3
int motorPin8 = 5; // Orange - In 4

int stepperSpeed = 1000; // Minimum Anzahl Mikrosekunden zwischen zwei Steps

void setup() {
pinMode(motorPin1, OUTPUT);
pinMode(motorPin2, OUTPUT);
pinMode(motorPin3, OUTPUT);
pinMode(motorPin4, OUTPUT);

pinMode(motorPin5, OUTPUT);
pinMode(motorPin6, OUTPUT);
pinMode(motorPin7, OUTPUT);
pinMode(motorPin8, OUTPUT);
}

void stepper1()
{ // 1
digitalWrite(motorPin4, HIGH);
digitalWrite(motorPin3, LOW);
digitalWrite(motorPin2, LOW);
digitalWrite(motorPin1, LOW);
delayMicroseconds(stepperSpeed);

// 2
digitalWrite(motorPin4, HIGH);
digitalWrite(motorPin3, HIGH);
digitalWrite(motorPin2, LOW);
digitalWrite(motorPin1, LOW);
delayMicroseconds(stepperSpeed);

// 3
digitalWrite(motorPin4, LOW);
digitalWrite(motorPin3, HIGH);
digitalWrite(motorPin2, LOW);
digitalWrite(motorPin1, LOW);
delayMicroseconds(stepperSpeed);

// 4
digitalWrite(motorPin4, LOW);
digitalWrite(motorPin3, HIGH);
digitalWrite(motorPin2, HIGH);
digitalWrite(motorPin1, LOW);
delayMicroseconds(stepperSpeed);

// 5
digitalWrite(motorPin4, LOW);
digitalWrite(motorPin3, LOW);
digitalWrite(motorPin2, HIGH);
digitalWrite(motorPin1, LOW);
delayMicroseconds(stepperSpeed);

// 6
digitalWrite(motorPin4, LOW);
digitalWrite(motorPin3, LOW);
digitalWrite(motorPin2, HIGH);
digitalWrite(motorPin1, HIGH);
delayMicroseconds(stepperSpeed);

// 7
digitalWrite(motorPin4, LOW);
digitalWrite(motorPin3, LOW);
digitalWrite(motorPin2, LOW);
digitalWrite(motorPin1, HIGH);
delayMicroseconds(stepperSpeed);

// 8
digitalWrite(motorPin4, HIGH);
digitalWrite(motorPin3, LOW);
digitalWrite(motorPin2, LOW);
digitalWrite(motorPin1, HIGH);
delayMicroseconds(stepperSpeed);
}

void stepper2()
{ // 1
digitalWrite(motorPin8, HIGH);
digitalWrite(motorPin7, LOW);
digitalWrite(motorPin6, LOW);
digitalWrite(motorPin5, LOW);
delayMicroseconds(stepperSpeed);

// 2
digitalWrite(motorPin8, HIGH);
digitalWrite(motorPin7, HIGH);
digitalWrite(motorPin6, LOW);
digitalWrite(motorPin5, LOW);
delayMicroseconds(stepperSpeed);

// 3
digitalWrite(motorPin8, LOW);
digitalWrite(motorPin7, HIGH);
digitalWrite(motorPin6, LOW);
digitalWrite(motorPin5, LOW);
delayMicroseconds(stepperSpeed);

// 4
digitalWrite(motorPin8, LOW);
digitalWrite(motorPin7, HIGH);
digitalWrite(motorPin6, HIGH);
digitalWrite(motorPin5, LOW);
delayMicroseconds(stepperSpeed);

// 5
digitalWrite(motorPin8, LOW);
digitalWrite(motorPin7, LOW);
digitalWrite(motorPin6, HIGH);
digitalWrite(motorPin5, LOW);
delayMicroseconds(stepperSpeed);

// 6
digitalWrite(motorPin8, LOW);
digitalWrite(motorPin7, LOW);
digitalWrite(motorPin6, HIGH);
digitalWrite(motorPin5, HIGH);
delayMicroseconds(stepperSpeed);

// 7
digitalWrite(motorPin8, LOW);
digitalWrite(motorPin7, LOW);
digitalWrite(motorPin6, LOW);
digitalWrite(motorPin5, HIGH);
delayMicroseconds(stepperSpeed);

// 8
digitalWrite(motorPin8, HIGH);
digitalWrite(motorPin7, LOW);
digitalWrite(motorPin6, LOW);
digitalWrite(motorPin5, HIGH);
delayMicroseconds(stepperSpeed);
}

unsigned long lastStepMicros;
const long stepMicros=1000L; // Anzahl Microsekunden zwischen zwei Schritten
int count;
void loop()
{
if (micros()-lastStepMicros>=stepMicros) // Schrittdauer ist um, mache einen Schritt
{
stepper1();
lastStepMicros+=stepMicros; // Zeit weiterzählen
count++; // Schrittzähler weiterzählen
if (count>=12) // Nach je 12 Schritten, mache einen Schritt mit dem zweiten Motor
{
stepper2();// Stepper soll an an dieser Stelle eine Umdrehung machen (ca. 4000 Steps) statt nur einen Schritt
count=0;
}
}
}

Muno:
Am Ende des Programms soll Stepper2 ja eine Umdrehung machen, also ca.4000 Steps.
Wie löse ich das am besten?

Die Bewegung in eine Funktion verlagern und diese Funktion 4000 Mal aufrufen.