Servomotor sweep mit gleichzeitgem DC-Motor beschleunigen

Hi Leute,

ich bin gerade dabei einen Spulenwickler mit einem DC-Motor als Antrieb und einem Servo als Drahführung zu bauen.
Die Schaltung funktioniert soweit schonmal ganz gut, allerdings habe ich noch ein Problem die beiden Motoren gleichzeitig anzusprechen.
Damit der Motor nicht ruckartig anläuft habe ich eine Schleife geschrieben welche die Drehzahl schrittweise erhöht.
Nun will ich gleichzeitig den Servo je nach geschwindigkeit des Motors in schwenken lassen.

Leider bekomme ich die Schleifen nicht richtig kombiniert. Der Servo läuft bis jetzt nur dann wenn der Motor beschleunigt wird. Danach soll der Servo aber weiterlaufen. Typisches Anfängerproblem :smiley:

Habt ihr einen Rat für mich?

Hier das Sketch:

//Motorkontrolle für einen Spulenwickler
#include <Servo.h> 
long movetime = 0;            
long smovetime = 0;           
int mDelay = 500;             
int sDelay = 8;               
int cPos;                     // Variable zum Speichern der Servoposition
int gPos;                     // Zielvariable zur Servoposition
int pin_motor = 3;            // Pin an dem das Gate des MOSFET angeschlossen ist
int tasterPin = 12;           // Taster an Pin 12
int on_led = 13;              // Grüne LED
int off_led =11;              // Rote LED
Servo myservo;


void setup()  { 
  pinMode(pin_motor, OUTPUT);
  pinMode(tasterPin, INPUT);
  pinMode(on_led, OUTPUT);
  pinMode(off_led, OUTPUT);
  myservo.attach(9);
  Serial.begin(9600);
}

void motor(int cV, int gV)  {
         while (cV < gV) {
         sweep();
         if (cV < gV && millis() >= movetime) {
         if (cV < gV) {
         analogWrite(pin_motor, cV+1);
         Serial.println(cV);
         cV =  cV++;
         }
         if (cV > gV) {
         analogWrite(pin_motor, cV-1);
         cV =  cV--;
         }
         if (cPos == gPos) {sweep();
         } // nothing
         movetime = millis() + mDelay;
         }        
      }
}
void sweep() {
   cPos = myservo.read();
   if (cPos == 70) gPos = 110;
   if (cPos == 110) gPos = 70;
   if (cPos != gPos && millis() >= smovetime) {
      if (cPos < gPos) myservo.write(cPos+1);
      if (cPos > gPos) myservo.write(cPos-1);
      smovetime = millis() + sDelay;}
 }

void loop()  {
  if(digitalRead(tasterPin) == HIGH) {
  digitalWrite(on_led, HIGH);
  digitalWrite(off_led, LOW);
  Serial.println("Anlaufen");
  motor(10,15);
  delay(8000);                                    
    
  Serial.println("1. Beschleunigen");
  motor(15,50);
  delay(3000);
   
  Serial.println("2. Beschleunigen");
  motor(50,80);
  delay(4000);
  
  Serial.println("Motor max");
  motor(80,100);
  delay(9000);
  analogWrite(pin_motor, 0);  
  }
  if(digitalRead(tasterPin) == LOW) {
  digitalWrite(on_led, LOW);
  digitalWrite(off_led, HIGH);
  //  Serial.println("warte...");
  }
}

Die Hälfte der Pausen machst Du mit millis() die andere mit delay(). das geht nicht.

Schmeiß delay() ganz raus.

Grüße Uwe

Sicherlich brauche ich die Delays() nicht, das ist auch nicht mein Problem. Vielmehr suche ich einen Weg, wie ich die Schleifen so umbauen kann, dass die Sweep Void weiterläuft auch wenn der Beschleunigungsvorgang vom Motor beendet ist.

und wenn Du an der DC-Motorwelle einen Kontakt / Lichtschranke oder ähnliches dazubaust und dann das Servo pro Umdrehung um einen definierten Weg vor und zurück bewegst?
So wie ich das verstehe, müsste der Servoarm sich pro Wellenumdrehung um den Wicklungsdrahtdurchmesser weiterbewegen und am Spulenende die Bewegung umkehren.
Sozusagen würde sich das Servo nicht entsprechend der verstrichenen Zeit bewegen, sondern entsprechend der effektiv schon erfolgten Wicklungen.

Gruß
Reinhard

So hab nochmal ne Nacht drüber geschlafen und nund hab ich das ganze wirklich Zeitgesteuert gemacht.

//Motorkontrolle für einen Spulenwickler
#include <Servo.h> 
long movetime = 0;            
long smovetime = 0;           
int mDelay = 500;             
int sDelay = 8;               
int cPos;                     // Variable zum Speichern der Servoposition
int gPos;                     // Zielvariable zur Servoposition
int pin_motor = 3;            // Pin an dem das Gate des MOSFET angeschlossen ist
int tasterPin = 12;           // Taster an Pin 12
int on_led = 13;              // Grüne LED
int off_led =11;              // Rote LED
Servo myservo;


void setup()  { 
  pinMode(pin_motor, OUTPUT);
  pinMode(tasterPin, INPUT);
  pinMode(on_led, OUTPUT);
  pinMode(off_led, OUTPUT);
  myservo.attach(9);
  Serial.begin(9600);
}

void motor(int cV, int gV,long waituntil)  {
         while (millis() <= waituntil) {               //Solange die Systemzeit <= der Wartezeit führe Schleife aus
         sweep();                                      //Aufrufen der Sweep Funktion
         if (cV != gV && millis() >= movetime) {
         if (cV < gV) {
         analogWrite(pin_motor, cV+1);
         Serial.println(cV);  
         cV =  cV++;
         }
         if (cV > gV) {
         analogWrite(pin_motor, cV-1);
         cV =  cV--;
         Serial.println(cV);
         }
         movetime = millis() + mDelay;
         }
         if (millis() >= waituntil) {break;}
         }      
}

void sweep() {
   cPos = myservo.read();
   if (cPos == 70) gPos = 110;
   if (cPos == 110) gPos = 70;
   if (cPos != gPos && millis() >= smovetime) {
      if (cPos < gPos) myservo.write(cPos+1);
      if (cPos > gPos) myservo.write(cPos-1);
      smovetime = millis() + sDelay;}
 }

void loop()  {
  if(digitalRead(tasterPin) == HIGH) {
  digitalWrite(on_led, HIGH);
  digitalWrite(off_led, LOW);
  Serial.println("Anlaufen");
  motor(10,15,10000);                             
  Serial.println("1. Beschleunigen");
  motor(15,50,22000);
  Serial.println("2. Beschleunigen");
  motor(50,80,30000);
  Serial.println(millis());
  Serial.println("Motor max");
  motor(80,100,32000);
  Serial.println(millis());
  Serial.println("Bremsen");
  motor(100,30,35000);
  analogWrite(pin_motor, 0);  
  }
  if(digitalRead(tasterPin) == LOW) {
  digitalWrite(on_led, LOW);
  digitalWrite(off_led, HIGH);
  }
}

@Spaceball keine schlechte Idee, mal sehen ob ich das dahingehend verändere

Du kannst nicht schreiben:

void motor(int cV, int gV, int waituntil)  {
         while (millis() <= waituntil) {

Da millis() einen Wert gibt, der von 0 raufzählt.
Du mußt den Anfangswert von millis() lesen und dann die Zeit dazuzählen wie Du es bei movetime machst.

void motor(int cV, int gV, int waituntil)  {
         waituntil=Millis()+waituntil;
         while (millis() <= waituntil) {

Außerdem kann analogrwrite Werte von 0 bis 255 entgegennehmen wobei 255 Höchstgeschwindigkeit ist.

Grüße Uwe

Ich bin echt überwälltigt wie viele Leute sich an so einer Problemlösung beteiligen - Super!

@ Uwe: Ich habe das so gelöst:

while (millis() <= time+waituntil) {

und in der loop()

void loop()  {
  if(digitalRead(tasterPin) == HIGH) {
  time = millis();
  digitalWrite(on_led, HIGH);
...

Der MOSFET macht scheinbar schon bei 100 ganz auf von daher wäre ein höherer Wert sinnlos.

Sieht so aus als funktioniere jetzt alles, nochmal Danke!

Der MOSFET macht scheinbar schon bei 100 ganz auf von daher wäre ein höherer Wert sinnlos.

Der mache nicht ganz auf sondern nur 100/255-stel Teil der Zeit. Es kann sein daß Dir der Motor auch bei nicht voller Ansteuerung schnell genug dreht.

Grüße Uwe