PWM Motor-SoftStart, nur einmal hochfahren ohne neuen Loop

Guten Tag
Ein Relais sendet 12V zum DC Motor. Damit der Motor langsam auf Touren kommt, habe ich vor, mit einem Arduino Nano mit PWM den Motor hochfahren zu lassen. Die Schaltung ist vorläufig mit einem FET auf einem Board aufgebaut. Soweit alles ok. Dachte ich...
Leider schaffe ich es nicht, dass der Loop nur einmal hochzählt und dann bleibt. Er startet immer wieder von Neuem.
Sobald ich aber die Leitung mit den 12V (über Spannungsteiler nach Pin 2) unterbreche, stoppt auch das Hochzählen auf dem Maximum. So sollte es sein.
Entweder ist mein Programm nicht dafür geeignet, oder ich finde den „Knopf im Kopf“ nicht.

const int switchPin = 2;                    // Programm StartPin
int motor = 9;                              // Motor Ausgabe auf MOSFET
int switchState = 0;                        // variable for reading the switch's status 


void setup() {   
   pinMode(motor, OUTPUT);                  // Motor Ausgang zum FET
   pinMode(switchPin, INPUT);               // Motorstrom "Schalter Eingang"
   
 Serial.begin(9600);  
 }   
   
  
void loop()  {  
  
  while( digitalRead(switchPin) == 1 )      // Motorstrom abfragen
  
{
  for (int fadeValue = 50; fadeValue <= 245; fadeValue += 10){  //Anfangs Wert; ** ;Hochzählschritte
    Serial.println(fadeValue);
    analogWrite(motor, fadeValue);
    delay(100);                             //Schnelligkeit hochzählen
  if (fadeValue==245) {
    fadeValue=255;                          // Endgeschwindigkeit (Max)
    break;
    }
   }   
  } 
 }

Als Lösung habe ich mir gedacht, ich könnte ja den Motorstrom als Impuls zum Pin 2 leiten. Mit meinen Versuchen (Blink ohne Delay) wollte das aber auch nicht klappen, weil die Pause wenn sie kurz ist immer wieder Impulse sendet, und wenn sie lange dauert einen neuen Impuls verhindert.

const int ledPin1 = 3;                  // Kontroll LED
const int tasterPin = 2;                // Taster Eingang ** Impulseingang
const unsigned long Ontime1 = 80;       // Andauer der LED ms ** Impulslänge
const unsigned long interval1 = 3000;   // Periodendauer (=AN + AUS) der LED ms 
unsigned long previousMillis1;

//int switchState = 0;                  // variable for reading the switch's status ** brauchts das?



void setup() {
  pinMode(ledPin1,OUTPUT);
  pinMode(tasterPin, INPUT);            
 
}

void loop()
{

if ( digitalRead(tasterPin) == HIGH )   
{  
  if (millis() - previousMillis1 > Ontime1){
    digitalWrite(ledPin1, LOW);
  }
  if (millis() - previousMillis1 > interval1){
    previousMillis1 = millis();   
    digitalWrite(ledPin1, HIGH);
    
  }  
 }
}

Seit Tagen am Foren durchforsten. Alles Probieren hat nichts gebracht.

LG Edy

Die Loop heißt nicht umsonst Loop, da es eine Schleife ist, die ständig durchlaufen wird.
Du musst deine Programmierung ändern damit das funktioniert.

Versuche es mal mit einem Merker (unetestet):

const int switchPin = 2;                    // Programm StartPin
const int motor = 9;                        // Motor Ausgabe auf MOSFET
bool motorstartet = 1;

void setup() {
  pinMode(motor, OUTPUT);                  // Motor Ausgang zum FET
  pinMode(switchPin, INPUT);               // Motorstrom "Schalter Eingang"

  Serial.begin(9600);
}


void loop()  {
  if (motorstartet)
  {
    for (int fadeValue = 50; fadeValue <= 245; fadeValue += 10) { //Anfangs Wert; ** ;Hochzählschritte
      Serial.println(fadeValue);
      analogWrite(motor, fadeValue);
      delay(100);                             //Schnelligkeit hochzählen
      if (!digitalRead(switchPin)) {   // Motorstrom abfragen
        break;
      }
    }
    motorstartet = false;
  }
}

Hi

Soll der Motor nur 1x hoch laufen und dann gut?
Dann ab mit dem Ablauf ins setup() und loop() leer lassen.
(wobei ich dann eine State-Maschine in der loop() vorziehen würde)

Klar - in der heutigen Zeit ist Das mit einem µC schneller getan, als Das über drei OpAmp (gibt's in einem Chip - dann ist sogar der Vierte arbeitslos) und zwei R-C-Gliedern aufzubauen.

Sobald der Motor auf 'Volle Kanne' läuft, kann man den Arduino schlafen schicken - spart wieder etwas Strom.

Wenn Das nicht 'der Kunst Schluß' sein soll - was hast Du vor?

MfG

PS: Bei dem 'motorstartet=false' könnte men den Tiefschlaf einleiten - oder im loop() andere Aufgaben erfüllen.
Wenn jetzt noch das delay() raus kommt (nur, sofern noch 'was Anderes' gemacht werden soll).

MfG²

@ HotSystems:
Das mit dem Loop ist mir klar. Auch im Setup habe ich den "Dauerlauf", solange der Motorstrom da ist.

@agmue:
So startet das Programm beim Anfangswert, 50, und bleibt da stehen. Kein Hochzählen.
Danke für den Hilfsansatz.

@ postmaster-ino:
Ja, nur einmal hochfahren und fertig.
Mit ab in den Setup, leider auch schon vor dem Post probiert. Gleiches Ergebnis.
µC hat hier den Vorteil, ich kann, wenn es dann mal geht :slight_smile: verschiedene Geschwindigkeiten und Anfangswerte über verschiedene Input Pin's abrufen.
Ich weiss, delay() hat hier nicht viele Freunde. Aber im Moment ist es mir hier noch nicht im Wege.

LG edy

epoxef:
@ HotSystems:
Das mit dem Loop ist mir klar. Auch im Setup habe ich den "Dauerlauf", solange der Motorstrom da ist.

Das ist nicht ganz richtig. Das Setup wird nur "einmal" je Start durchlaufen, was dein Motor dabei macht, ist eine andere Sache.
Klar, wenn du den im Setup startest und nicht wieder ausschaltest, ist dieser im Dauerlauf, auch wenn das Setup lange verlassen wurde.

Hi

Ok, 1x hoch laufen - dann auslaufen lassen, oder an lassen?
Packe den Kram ins setup()
Am Schluß vom setup() stoppst Du den Motor (wenn Er auslaufen soll), oder machst Nichts weiter.
Die loop() bleibt dann leer.
Wenn jetzt der Motor öfter hochläuft, schmiert Dir der Arduino ab, resettet und startet neu - woher bekomme Der Seinen Strom?

Du musst aber schon präzisieren, was Du machen willst.
Auch, wenn Das für Dich sonnenklar ist, wir kennen weder Dein Ausgangs-Problem, noch Deine Gedanken, Die Da schon investiert hast.

MfG

Alles ins setup() gepackt. (Sketch von agmue)
Loop leer.

Gleiches Ergebnis. Nur Anfangswert (50).

Der Motor soll, nach dem das externe Relais den Strom liefert, hochfahren. Dann auf dem max. Level bleiben. Das ext. Relais schaltet nach 3 Minuten den Motorstrom wieder ab.

Der Arduino bekommt den Strom vom gleichen Akku, wie das Motor-Relais. Auf 5V geregelt und dauernd.

Die Anwendung ist für dynamisches Feuerwerk. Das Motormodul ist irgendwo in der Landschaft. Per Funkzündung wird die Zündung des Feuerwerkskörpers ausgelöst. Etwas später, nach hochfahren der Feuerwerkskörpers beginnt der Motor (Timer-Relais) zu drehen. Nach ca 3 Minuten stellt der Motor wieder ab. Ende des Spektakels.
Bis jetzt schaltet der Motor einfach "hau ruck" ein. Schöner wäre, wenn er sanft zu drehen begänne. Das möchte ich erreichen.
LG edy

epoxef:
@agmue:
So startet das Programm beim Anfangswert, 50, und bleibt da stehen. Kein Hochzählen.

Dann schmeiß mal das Ausrufezeichen raus, dreht die Logik um:

if (digitalRead(switchPin)) {   // Motorstrom abfragen

Besten Dank
Komme heute kaum mehr dazu, mich damit zu beschäftigen.
Ein kurzer Test zeigt: Nach dem Hochladen einmal hochzählen.
Vor dem ersten Hochzählen ein "Fehlstart" bis ca.130, dann von 50 bis 240.
Pin 2 ist jetzt nicht mehr eingebunden. Er wäre für den Start zuständig.
Deshalb ist ein verschieben in den Setup meiner Meinung nach nicht möglich.
Mit Pin 2 wird das Programm aktiviert, nicht beim Einschalten des Arduino.
LG edy

Verwirrend Du sprichst.
Nix verstehen ich tu.

Wie äußert sich der 'Fehlstart'?
Hochlaufen bis 'ca. 130' (woher kommt dieser Wert?)
Danach 'Hochlaufen von 50 bis 240' - dito, woher kommen diese Werte?

Wenn Du serielle Ausgaben bekommst - schaden Die hier nicht.
Wenn Du keine seriellen Ausgaben bekommst - bau Welche ein.

MfG

epoxef:
Vor dem ersten Hochzählen ein "Fehlstart" bis ca.130, dann von 50 bis 240.

Dann flattert der Eingangspin, es fehlt ein Pullup- oder PullDownwiderstand.

Hallo,

wenn ich stören darf. Ohne kompletten Schaltplan bleibt das verwirrend. Wie ist der Eingang beschalten? Wie ist der Mosfet beschalten? Wie ist das Relais verschalten? Usw. ... Selbst die beste Glaskugel benötigt etwas Licht im Dunkeln.

Doc_Arduino:
wenn ich stören darf.

Naja, ausnahmsweise.

Doc_Arduino:
Selbst die beste Glaskugel benötigt etwas Licht im Dunkeln.

Ich habe keine Glaskugel, Uwe wollte mir auch keine gebrauchte zugestehen, da brauche ich auch kein Licht :grin:

Inzwischen habe ich mein Programm aus #2 getestet und es macht, was ich von ihm erwarte: Es zählt genau einmal von 50 bis 240, wobei ich switchPin auf HIGH gelegt habe.

Doc_Arduino:
wenn ich stören darf.

Möglicherweise ist es sogar unbedingt notwendig :slight_smile:

:slight_smile: Keine gebrauchte Glaskugel von Uwe, na sowas aber auch.
Ich drücke dir/euch die Daumen das alles zusammen findet.

epoxef:
Mit Pin 2 wird das Programm aktiviert, nicht beim Einschalten des Arduino.

Aha, bei mir wird die Schleife mit switchPin vorzeitig beendet. Da steht ja: "Motorstrom abfragen" und nicht "starte Motor".

Möglicherweise so (ungetestet):

const int startPin = 2;                     // Programm StartPin
const int motor = 9;                        // Motor Ausgabe auf MOSFET
bool motorstartet = 1;

void setup() {
  pinMode(motor, OUTPUT);                  // Motor Ausgang zum FET
  pinMode(startPin, INPUT);
  Serial.begin(9600);
  Serial.println("Warte auf Start");
  while (!digitalRead(startPin)) {         // Start bei HIGH
    Serial.print('.');
    delay(100);
  }
  Serial.println("\nStart!");
}


void loop()  {
  if (motorstartet)
  {
    for (int fadeValue = 50; fadeValue <= 245; fadeValue += 10) { //Anfangs Wert; ** ;Hochzählschritte
      Serial.println(fadeValue);
      analogWrite(motor, fadeValue);
      delay(100);                             //Schnelligkeit hochzählen
    }
    motorstartet = false;
  }
}

Oder alternativ in loop (ungetestet):

const int startPin = 2;                     // Programm StartPin
const int motor = 9;                        // Motor Ausgabe auf MOSFET
byte status = 0;
byte fadeValue = 50;

void setup() {
  pinMode(motor, OUTPUT);                  // Motor Ausgang zum FET
  pinMode(startPin, INPUT);
  Serial.begin(9600);
  Serial.println("Warte auf Start");
}


void loop()  {
  switch(status)
  {
    case 0:
      Serial.print('.');
      delay(100);
      if(digitalRead(startPin)) {
        status++;
        Serial.println("\nStart!");
      }
      break;
    case 1:
      analogWrite(motor, fadeValue);
      Serial.println(fadeValue);
      delay(100);                             //Schnelligkeit hochzählen
      if(fadeValue <= 245) {
        fadeValue += 10;
      } else {
        status++;
      }
    }
  }
}

Guten Tag

Gestern war mein Test nur auf die Schnelle passiert. Hatte kaum Zeit. Antworten wollte ich aber trotzdem schnell.
Tut mir leid, dass ich die hilfsbereiten Cracks verwirrte und die Glaskugel in der Finsternis nicht lesbar war.
Vorab: Es läuft!
@postmaster-ino: Die serielle Ausgabe lieferte mir diese Werte.
@agmue: -PullDown war vorhanden. Trotzdem, in diese Richtung musste es gehen.
-Danke für dein Testen. Wenn’s bei dir geht, wieso sollte es bei mir klemmen?
Nach dem switchPin Einbau lief auch meine Schaltung.
Hier der Sketch, wie ich ihn nun nutze:

const int switchPin = 2;                    // Programm StartPin
const int motor = 9;                        // Motor Ausgabe auf MOSFET
bool motorstartet = 1;

void setup() {
  pinMode(motor, OUTPUT);                   // Motor Ausgang zum FET
  pinMode(switchPin, INPUT);                 // Motorstrom "Schalter Eingang"

  Serial.begin(9600);
}


void loop()  {
if ( digitalRead(switchPin) == 1 )          // Motorstrom abfragen
  
  if (motorstartet)
  {
    for (int fadeValue = 50; fadeValue <= 250; fadeValue += 1) { //Anfangs Wert; ** ;Hochzählschritte
      Serial.println(fadeValue);
      analogWrite(motor, fadeValue);
      delay(100);                           //Schnelligkeit hochzählen
      if (!digitalRead(switchPin)) {        // Motorstrom abfragen
        break;
      }
    }
    motorstartet = false;
  }
}

Ich macht den Fehler, dass ich das Startsignal auf dem Breadboard an einer „zugänglichen“ Stelle unterbrach und nicht am Eingang. Fatal! Der PullDown war dann auch unterbrochen. Daher die Fehler beim Hochladen. Mit den Nachfolgefehlern.
Da begreife ich, dass bei euch die Verwirrung komplett war.

@Doc_Arduino: Was heisst hier stören? Jede Hilfeleistung ist mir willkommen, ich stehe mit dem Arduino noch ganz am Anfang. LOGO! von Siemens war bis jetzt mein Favorit. Ist halt ein bisschen gross... und teuer. Aber die Programmierung lag mir.
Schaltplan im Anhang.

Vielen Dank für die Hilfe. Ich war echt am „Berg“.
LG edy

SoftStart.jpg

Sorry agmue, habe deinen letzten Post übersehen.
Nehme in mir noch vor. Hat sicher noch ein paar Leckerbissen drin.
BestenDank
LG edy

Beide Versionen getestet.
Wunderbar!
Klemme mich nun dahinter, deinen verfeinerten Code zu verstehen.
Manchmal braucht es einen Schubser von Extern, damit es weitergeht.
Vielen Dank, allen.
LG edy

Dann noch die Variante ohne delay:

const int startPin = 2;                     // Programm StartPin
const int motor = 9;                        // Motor Ausgabe auf MOSFET
uint32_t aktMillis, fadeMillis;
const uint32_t fadeIntervall = 100;
byte status = 0;
byte fadeValue = 50;

void setup() {
  pinMode(motor, OUTPUT);                  // Motor Ausgang zum FET
  pinMode(startPin, INPUT_PULLUP);
  Serial.begin(9600);
  Serial.println("Warte auf Start");
}


void loop()  {
  aktMillis = millis();
  switch (status)
  {
    case 0:
      if (digitalRead(startPin)) {
        status++;
        Serial.println("Start!");
      }
      break;
    case 1:
      if (aktMillis - fadeMillis >= fadeIntervall) {
        fadeMillis = aktMillis;
        analogWrite(motor, fadeValue);
        Serial.println(fadeValue);
        if (fadeValue <= 245) {
          fadeValue += 10;
        } else {
          status++;
        }
      }
  }
}