Forum: Compiler & IDEs Ansteuerung eines Schrittmotors mit 2 Endschaltern


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von Jens R. (homerqlb)


Bewertung
0 lesenswert
nicht lesenswert
Hallo ihr Programmierexperten,
Ich habe folgendes Projekt mit einem Entwicklungsboard vor:
Per Tasterdruck soll ein Relais geschaltet werden, nach ca. 5 Sek. soll 
ein 2 Phasen Schrittmotor losdrehen und bis zur Betätigung eines 
Endschalters fahren, dort anhalten, das zuerst geschaltete Relais 
abschalten ca.5 Sek. warten und wieder zurücklaufen bis zu einem anderen 
Endschalter. Dort angelangt soll er anhalten. Das war`s. Der 2. 
Endschalter ist also zu Beginn geschaltet.
Hat jemand soetwas schon einmal programmiert?
Oder gibt es Tipps für die Herangehensweise.
Ich blutiger Anfänger, was das Programmieren angeht.
Die nötige Software (Arduino 1.8.12) habe ich schon installiert.
Einen kleinen Crashkurs hab ich mir auch schon verpaßt.
Das Board ist folgendes:
Ebay-Artikel Nr. 193164761872
Das Relais:
Ebay-Artikel Nr. 142889819573
Die Schrittmotortreiberstufe:
Ebay-Artikel Nr. 252784175280
Die Endschalter sind Rollenschalter

von Wolfgang (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Jens R. schrieb:
> Hat jemand soetwas schon einmal programmiert?

Nein, für Schrittmotoren wäre diese Art der Steuerung eher ungewöhnlich.
Wozu soll das Relais gut sein. Ein Schrittmotor läuft nicht einfach los 
und fährt dann bis zu einem Endschalter. Ein Schrittmotor muss jeden 
einzelnen Schritt gesagt bekommen und die Anzahl der Schritte bestimmt 
den Fahrweg. Da braucht man keinen Endschalter. Es reicht eine 
Referenzmarke, an der sich der µC orientieren kann. Alles andere ist 
Schrittzählerei. Damit er beim Losfahren und Abbremsen keine Fehler 
macht, muss die Schrittfrequenz als Rampe ansteigen und zum Anhalten 
wieder absinken.

von Jens R. (homerqlb)


Bewertung
0 lesenswert
nicht lesenswert
Das Relais schaltet einen Motor an, der erst auf Touren kommen muß, 
deshalb die 5 Sek. Wartezeit, ehe der Schrittmotor loslaufen soll. der 
treibt einen Schlitten auf einer Linearachse an, der bis zur Endlage 
fahren, dort soll der Andere Motor abgeschaltet werden und abtouren, 
deshalb wieder 5 Sek. warten und wieder zur Ausgangspos. zurückfahren.
Erfahrungsgemäß kommt es bei Schrittmotoren zu Schrittverlusten, aus 
unterschiedlichen Gründen. Somit würde sich die Position immer mehr 
verschieben. Die Endschalter wären sozusagen eine Sicherheit, aber wenn 
das mit der einfachen Zählerrei auch gut funktioniert, könnte ich es so 
machen. Das vereinfacht das Ganze erheblich, ich habe da glaube ich 
schon einen Code in einer Bibliothek gesehen. Das mit der Rampe macht es 
wieder komplizierter.
Näheres zum Projekt hier:
Beitrag "Vorschubsteuerung für Gehrungssäge"

von tommy (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Hallo Jens,
mach doch bitte nicht mehrere Threads zu einem Thema auf.

Hier in "Compiler und IDEs" bist Du sowieso völlig falsch.

Jens R. schrieb:
> Ich blutiger Anfänger, was das Programmieren angeht.

Mein Tip:
Klein anfangen, dann hat man schneller Erfolgserlebnisse.
Fang damit an, eine LED blinken zu lassen.
Wenn Du am Anfang gleich ein komplexes Projekt angehst,
dann ist die Gefahr gross, dass das Interesse nachlässt,
wenn es nicht funktioniert.

Jens R. schrieb:
> Das Relais schaltet einen Motor an

Was für ein Motor?
Es gibt bestimmt bessere, elektronische Möglichkeiten.
Vermeidet dann z.B. den Abreissfunken beim Ausschalten.

Jens R. schrieb:
> Erfahrungsgemäß kommt es bei Schrittmotoren zu Schrittverlusten, aus
> unterschiedlichen Gründen.

Das passiert nur Bastlern.
Wenn man das als professioneller Elektronikentwickler angeht, dann
ermittelt man vorab das benötigte Drehmoment.
Dann programmiert man die Fahrt mit Beschleunigungs- und
Bremsrampen.

Jens R. schrieb:
> ich habe da glaube ich
> schon einen Code in einer Bibliothek gesehen

Das Programm ohne Nutzung fremder Bibliotheken (Libraries) zu
schreiben hat einen viel höheren Lernfaktor ;-)

P.S.: Du scheinst schon etwas älter zu sein, denn ich meine in
einem der anderen Threads "220V" gelesen zu haben. Das war einmal ;-)

von Wolfgang (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Jens R. schrieb:
> Erfahrungsgemäß kommt es bei Schrittmotoren zu Schrittverlusten, aus
> unterschiedlichen Gründen.

Dann ist der Antrieb falsch dimensioniert.
Positionssensensorik bei Schrittmotoren ist nur eine Krücke, um das zu 
vertuschen.

Ein Schrittmotor, der bei höherer Schrittgeschwindigkeit einem Schritt 
des Feldes nicht richtig folgen kann, bleibt rappelnd hängen und folgt 
dem Feld erst wieder nach drastischer Reduzierung der Schrittfrequenz.

Es reicht, wenn es irgendwo auf der Fahrstecke eine Referenzmarke gibt 
und die Steuerung weiss, in welcher Fahrtrichtung sich die Marke 
befindet.

von Wolfgang (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Jens R. schrieb:
> Das mit der Rampe macht es wieder komplizierter.

Ohne Rampen werden dir höhere Schrittfrequenzen verwehrt bleiben.
Soooh kompliziert ist das nun auch wieder nicht.

Von Atmel gibt es für Rampen mit konstanter Beschleunigung eine recht 
einfache Darstellung in der AN_8017:

Atmel AppNote AVR446 - Linear speed control of stepper motor
http://ww1.microchip.com/downloads/en/AppNotes/doc8017.pdf

und dazu den Code
http://ww1.microchip.com/downloads/en/AppNotes/AVR446.zip

von Jens R. (homerqlb)


Bewertung
0 lesenswert
nicht lesenswert
tommy schrieb:
> Hallo Jens,
> mach doch bitte nicht mehrere Threads zu einem Thema auf.
>
Es handelt sich um unterschiedliche Aspekte in meinem Projekt, die in 
unterschiedlichen Themengruppen behandelt werden. Ich möchte die 
Experten, die sich in den entsprechenden Themengruppen umsehen, 
erreichen.
> Hier in "Compiler und IDEs" bist Du sowieso völlig falsch.
>
Es geht mir hier nur um die Programmierung, welche Gruppe wäre dann hier 
die richtige?
>> Das Relais schaltet einen Motor an
>
> Was für ein Motor?
> Es gibt bestimmt bessere, elektronische Möglichkeiten.
> Vermeidet dann z.B. den Abreissfunken beim Ausschalten.
Da geht es um die Elektronik, das in einem anderen Themengebiet 
behandelt wird
>
> Das Programm ohne Nutzung fremder Bibliotheken (Libraries) zu
> schreiben hat einen viel höheren Lernfaktor ;-)
O.K. werde ich versuchen.
> P.S.: Du scheinst schon etwas älter zu sein, denn ich meine in
> einem der anderen Threads "220V" gelesen zu haben. Das war einmal ;-)
>
Ja Ü50, jetzt sind es wohl 230V die Umstellung ist mir doch glatt 
entgangen.

von Jens R. (homerqlb)


Bewertung
0 lesenswert
nicht lesenswert
Ich danke für die Belehrungen in Bezug auf Schrittmotoren, aber in einem 
anderen Beitrag war jemand der Meinung, dass wenigstens ein Schalter 
sein muß. Nun ja so ist das halt.
Ich bin nur ein kleiner Bastler, der eine Idee umzusetzen versucht.
Wenn`s nicht funktioniert bleibe ich bei Handbetrieb.
Wie gesagt, hier geht es nur um`s Programmieren.
Ich fange mal an und bitte euch um eure Meinung.

von Wolfgang (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Jens R. schrieb:
> ... aber in einem anderen Beitrag war jemand der Meinung, dass wenigstens
> ein Schalter sein muß.

Benötigt wird ein Positionssensor. Das kann z.B. eine Lichtschranke 
irgendwo auf dem Weg sein, die dem Contoller mitteilt: "Der Schlitten 
ist jetzt beim Sensor".

von Udo K. (udok)


Bewertung
0 lesenswert
nicht lesenswert
Und um was geht es genau?

Oder ist das wieder so ein supergeheimes Ding aus dem 
Verteidigungsministerum?

von Jens R. (homerqlb)


Bewertung
-1 lesenswert
nicht lesenswert
Wolfgang schrieb:
> Jens R. schrieb:
>> ... aber in einem anderen Beitrag war jemand der Meinung, dass wenigstens
>> ein Schalter sein muß.
>
> Benötigt wird ein Positionssensor. Das kann z.B. eine Lichtschranke
> irgendwo auf dem Weg sein, die dem Contoller mitteilt: "Der Schlitten
> ist jetzt beim Sensor".

Warum dann nicht ein Rollenschalter, den habe ich gerade da, am Wegende?
Und wenn da schon einer ist, kann doch am Weganfang auch einer sein, den 
habe ich nähmlich auch gerade da.
Ich arbeite an einer CNC-Maschine mit hochgenauen Messsystem, trotzdem 
gibt es auch hier noch Endschlter!
Ist das dann auch unnötig? Dann bau ich sie heute noch aus.

von Jens R. (homerqlb)


Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Udo K. schrieb:
> Und um was geht es genau?
>
> Oder ist das wieder so ein supergeheimes Ding aus dem
> Verteidigungsministerum?

Nein natürlich nicht.
Also ich habe mir eine Gehrungssäge gebaut.
Eine Kreissäge angetrieben von einem Brushlessmotor.
Die Säge sitzt auf einem Schlitten, der hin und her rutscht.
Damit ich das Ganze nicht mehr von Hand betätigen muß und um weit weg 
von gefährlichen sich drehenden Teilen zu sein soll die Hin-Herbewegung 
automatisch erfolgen.
Also wie folgt:
-Sägenmtor an
-hochtouren lassen
-Vorschub an
-am Ende der Wegstrecke angelangt anhalten
-Sägenmotor abschalte
-abtouren
-Vorschub zurück in Ausgangslage
und aus
Anbei mal ein Bild davon

von Jens R. (homerqlb)


Bewertung
0 lesenswert
nicht lesenswert
Ich beginne mal mit einer Trockenübung:
Ich habe mal versucht einen Code zu schreiben, um das Relais am Anfang 
einzuschalten und eingeschaltet zu lassen.
Bitte nicht lachen, es sind meine ersten Gehversuche.

void setup() {
pinMode(2,OUTPUT);
pinMode(3,INPUT);
}

void loop() {
if (digitalRead(3)==HIGH;digitalRead(2)==LOW)
{
  digitalWrite(2,HIGH)
  else digitalWrite(2,HIGH)}
}

Mich verwirrt, die Schleife (void loop) warum kann ich das Relais nicht 
einfach einschalten und weiter im Programm?

von Wolfgang (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Jens R. schrieb:
> Warum dann nicht ein Rollenschalter,
> ...
> Ich arbeite an einer CNC-Maschine mit hochgenauen Messsystem, trotzdem
> gibt es auch hier noch Endschlter!
> Ist das dann auch unnötig? Dann bau ich sie heute noch aus.

Rollenschalter sind eher nicht hochgenau, also nicht zur 
Positionsbestimmung geeignet. Du solltest zwischen Maschinensteuerung 
und Sicherheitstechnik unterscheiden.

von Jens R. (homerqlb)


Bewertung
0 lesenswert
nicht lesenswert
Wolfgang schrieb:
> Jens R. schrieb:
>> Warum dann nicht ein Rollenschalter,
>> ...
>> Ich arbeite an einer CNC-Maschine mit hochgenauen Messsystem, trotzdem
>> gibt es auch hier noch Endschlter!
>> Ist das dann auch unnötig? Dann bau ich sie heute noch aus.
>
> Rollenschalter sind eher nicht hochgenau, also nicht zur
> Positionsbestimmung geeignet. Du solltest zwischen Maschinensteuerung
> und Sicherheitstechnik unterscheiden.

Hochgenau positionieren möchte ich nicht, für mich sind die 
Rollenschalter sicherheitstechnisch relevant, da sie die Endlage 
kontrollieren, sonst kann ich sie auch weglassen. Ich denke eine Abfrage 
der Schalter sollte programmtechnisch eher gering im Aufwand sein und da 
sie sowieso vorhanden sind kann es ja nicht schaden.
In meiner kleinen Fräse im Keller sind auch diese Dinger verbaut und 
funktionieren seit 3 Jahren reibungslos, wie gesagt nur als Endschalter.

von Harald W. (wilhelms)


Bewertung
0 lesenswert
nicht lesenswert
Jens R. schrieb:

> Per Tasterdruck soll ein Relais geschaltet werden, nach ca. 5 Sek. soll
> ein 2 Phasen Schrittmotor losdrehen und bis zur Betätigung eines
> Endschalters fahren, dort anhalten,

Warum nimmst Du da nicht einfach einen DC-Motor? Dann funktioniert
die Schaltung ganz ohne Elektronik.

von M. K. (mkn)


Bewertung
0 lesenswert
nicht lesenswert
Wolfgang schrieb:
> Nein, für Schrittmotoren wäre diese Art der Steuerung eher ungewöhnlich.

Nicht wenn man definierte Drehzahlen bei unterschiedlichen 
Lastverhältnissen braucht. Da sind Stepper durchaus eine einfache 
Möglichkeit.

@TO:
Du erzeugst doch die Step und Direction Signale für die 
Schrittmotortreiber.
Was genau ist jetzt das Problem diese höchst einfache Aufgabe in einen 
zeitlichen Programmablauf zu drücken?
Mit zwei Pins für die Stepper wackeln.
delay_ms() verwenden und mit zwei weiteren Pins für die Reails wackeln.

von Jens R. (homerqlb)


Bewertung
0 lesenswert
nicht lesenswert
Mir ist ein Licht aufgegangen.

Jens R. schrieb:
> Mich verwirrt, die Schleife (void loop) warum kann ich das Relais nicht
> einfach einschalten und weiter im Programm?

Ich versuche mir mal selbst zu antworten,
der µC fängt sofort wenn er unter Strom steht das gespeicherte Programm 
abzuarbeiten an, ohne Anstoß von außen.
Wäre da nicht dieses dauernde Durchlaufen, könnte man höchstens einen 
Code ausführen, Eingaben könnten aber nicht überwacht werden.
Richtig?
Wieder was gelernt!
Sollte ich jetzt für den Code einen neuen Beitrag eröffnen in der 
entsprechenden Gruppe?
Die älteren Beiträge könnten geschlossen werden, weil erledigt.
Wie macht man den so etwas.

von MaWin (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Jens R. schrieb:
> Erfahrungsgemäß kommt es bei Schrittmotoren zu Schrittverlusten, aus
> unterschiedlichen Gründen.

Welche Erfahrung sol das sein ?

Deine Erfahrung ? Ich dachte, du hast keine Erfahrung.

Ein Schrittmotor, der Schritte verliert, wurde falsch eingesetzt.

Jens R. schrieb:
> Bitte nicht lachen, es sind meine ersten Gehversuche.
>
> void setup() {
> pinMode(2,OUTPUT);
> pinMode(3,INPUT);
> }
>
> void loop() {
> if (digitalRead(3)==HIGH;digitalRead(2)==LOW)
> {
>   digitalWrite(2,HIGH)
>   else digitalWrite(2,HIGH)}
> }
>
> Mich verwirrt, die Schleife (void loop) warum kann ich das Relais nicht
> einfach einschalten und weiter im Programm?

Ja, das sind sehr die Anfänge.

Benutze zum Betrieb eines Schrittmotortreibers an einem Arduino eine 
Library wie https://www.airspayce.com/mikem/arduino/AccelStepper/
denn die eingebaute https://www.arduino.cc/en/Reference/Stepper
kann keine Schrittmotortreiber mit DIR und STEP Anschlüssen
#include <AccelStepper.h>
AccelStepper myStepper(AccelStepper::DRIVER , 8, 9); // Schrittmotortreiber an Pin 8 und 9

Dein setup nutzt Pin3 für den Taster, Pin2 für das Relais, du brauchst noch einen Endschalter an Pin4 und einen Anfangsschalter auf Pin5.

Dein loop sollte auf den Tastendruck warten

enum {WARTE_AUF_TASTER,FAHRE_VORWAERTS,FAHRE_RUECKWAERTS} zustand=WARTE_AUF_TASTER;

void loop()
{
  myStepper.run();
  switch(zustand)
  {
  case WARTE_AUF_TASTER:
    if(digitalRead(2)) // Taster heruntergedrückt
    {
        digitalWrite(2,HIGH); // Relais einschalten
        delay(5000); // 5 Sekunden warten
        myStepper.move(1000);
        zustand=FAHRE_VORWAERTS;
    }
    taster_was_down=taster_down;
    break;
  case FAHRE_VORWAERTS:
    if(digitalRead(4)) // Endschalter 1 erreicht
    {
        myStepper.stop();
        digitalWrite(2,LOW); // Relais ausschalten
        delay(5000); // 5 Sekunden warten
        myStepper.move(-1000);
        zustand=FAHRE_RUECKWAERTS;
    }
    break;
  case FAHRE_RUECKWAERTS:
    if(digitalRead(5)) // Endschalter 2 erreicht
    {
        myStepper.stop();
        zustand=WARTE_AUF_TASTER;
    }
    break;
}
So in der Art. Wobei delay und run wohl nicht zusammenpassen.

von Jens R. (homerqlb)


Bewertung
0 lesenswert
nicht lesenswert
MaWin schrieb:
> Jens R. schrieb:
>> Erfahrungsgemäß kommt es bei Schrittmotoren zu Schrittverlusten, aus
>> unterschiedlichen Gründen.
>
> Welche Erfahrung sol das sein ?
>
> Deine Erfahrung ? Ich dachte, du hast keine Erfahrung.
>
> Ein Schrittmotor, der Schritte verliert, wurde falsch eingesetzt.
Erfahrungen von meiner CNC Eigenbaufräse im Keller.
Die wird von einer Software betrieben, da habe ich mir noch keine 
Gedanken über den Code gemacht, der diese ansteuert.

von Jens R. (homerqlb)


Bewertung
0 lesenswert
nicht lesenswert
MaWin schrieb:
> Benutze zum Betrieb eines Schrittmotortreibers an einem Arduino eine
> Library wie https://www.airspayce.com/mikem/arduino/AccelStepper/
> denn die eingebaute https://www.arduino.cc/en/Reference/Stepper
> kann keine Schrittmotortreiber mit DIR und STEP Anschlüssen
> [c]
> #include <AccelStepper.h>
> AccelStepper myStepper(AccelStepper::DRIVER , 8, 9); //
> Schrittmotortreiber an Pin 8 und 9
>
> Dein setup nutzt Pin3 für den Taster, Pin2 für das Relais, du brauchst
> noch einen Endschalter an Pin4 und einen Anfangsschalter auf Pin5.
>
> Dein loop sollte auf den Tastendruck warten
Ist klar der Code ist Mist.
Ich habe mich auch schon etwas weiter informiert.
Erstmal Dank für die konstruktive Hilfe!
Ich habe mir auf nem Zettel schon ein bisschen Code zusammengebastelt, 
der muß nur noch eigegeben werden.
Die Teile sind unterwegs, so mache ich jetzt Trockenübungen.
Einen Simulator will ich mir auch noch installieren.
Durch den Schrittmotortreiber muß ich, wenn ich richtig verstenden habe, 
doch nur ein Dir-Signal auf Dir-Pin (High oder Low) senden und der Takt 
wäre dann nur High, Delay, Low, Delay Auf Step-Pin.
Ist das nicht so?

von Jens R. (homerqlb)


Bewertung
0 lesenswert
nicht lesenswert
Hier mein Code bisher:
int RelPin = 1; //Relais
int DirPin = 2; //Dir Schrittmotor
int RelPin = 3; //Step Schrittmotor
int EndPin = 4; //Endschalter
int AnfPin = 5; //Anfangsschalter
int Startpin = 2; //Starttaster


void setup() {
  pinMode(1; OUTPUT); //Relais
  pinMode(2; OUTPUT); //Dir Schrittmotor
  pinMode(3; OUTPUT); //Step Schrittmotor
  pinMode(4; OUTPUT); //Endschalter
  pinMode(5; OUTPUT); //Anfangsschalter
  pinMode(6; INPUT); //Starttaster
}

void loop() {
  digitalRead(StartPin)//Abfrage Starttaster
  if (StartPin == HIGH) { //Wenn Starttaster gedrückt
    digitalWrite(RelPin, HIGH) //Sägenmotor an
    delay(5000) //Wartezeit zum Sägenmotor hochtouren
    digitalWrite(dirPin, HIGH) //Richtung Schrittmotor
    While(EndPin, HIGH) { //Schleife solange Endschalter micht geschaltet
      //Hier soll noch  die Beschleunigung rein
      digitalWrite(StepPin, HIGH) //Signal Schrittmotor
      delay(10) //Pausenlänge für Geschwindigkeit
      digitalWrite(StepPin, LOW) //Signal Schrittmotor
      delay(10) //Pausenlänge für Geschwindigkeit
    }
    digitalWrite(RelPin, LOW) //Sägenmotor aus
    delay(5000) //Abtouren Sägenmotor
    digitalWrite(dirPin, LOW) //Richtungsumkehr Schrittmotor
    While(AnfPin, HIGH) { //Schleife solange Anfangsschalter micht geschaltet
      //Hier soll noch die Beschleunigung rein
      digitalWrite(StepPin, HIGH) //Signal Schrittmotor
      delay(10) //Pausenlänge für Geschwindigkeit
      digitalWrite(StepPin, LOW) //Signal Schrittmotor
      delay(10) //Pausenlänge für Geschwindigkeit
    }
  }
}

von Johannes S. (jojos)


Bewertung
0 lesenswert
nicht lesenswert
'state machine' wäre ein Stichwort um passendes Futter zu suchen. Damit 
wird es etwas übersichtlicher und auch so Sachen wie Schnell/Nothalt 
besser zu realisieren.

von Jens R. (homerqlb)


Bewertung
-1 lesenswert
nicht lesenswert
Johannes S. schrieb:
> 'state machine' wäre ein Stichwort um passendes Futter zu suchen. Damit
> wird es etwas übersichtlicher und auch so Sachen wie Schnell/Nothalt
> besser zu realisieren.

Naja zumindest kein: "Oh Gott, was für ein Müll."
In einer letzten Antwort wurde mir geraten, Bibliotheken zu meiden, um 
etwas dazuzulernen. Das habe ich auch vor.
Bevor noch Fragen wie : "Du hast noch nie zuvor programmiert?" kommen, 
ja ich habe verschieden Sachen mit Excel ausprobiert und auf der Arbeit 
"programmiere" ich Tag täglich, eine CNC-Maschine mit 
Heidenhain-Steuerung.
Jaja, von wegen programmieren, aber das Grundverständnis von Schleifen 
und Abfragen ist auch dort wichtig und in gewissen Maße kann man da auch 
richtig "programmieren".

von M. K. (mkn)


Bewertung
0 lesenswert
nicht lesenswert
Jens R. schrieb:
> Naja zumindest kein: "Oh Gott, was für ein Müll."

Wenns funktioniert, ist es kein Müll.

Die Delay Kontruktionen haben nur den Nachteil, das die MCU sich dabei 
im Kreis dreht und nix anderes währenddessen macht.

Ich schreibe mir für sowas eine Timer ISR die alle xx ms ein flag setzt.
Muss nicht schneller sein als die kürzenste Zeitspanne die Du benötigst.
Mit Statemachine löscht Du das Flag, tackerst Du die verschiedenen 
Zustände der Reihe nach durch und zählst im entsprechendne State den 
jeweiligen Counter hoch und triffst die Entscheidung ob die Zeit 
abgelaufen ist.

Danach gehts zurück ins Hauptprogramm und Du kannst alles andere 
erledigen.
Z.B. Nothalt.
So springst Du nur jeweils zu den Timer Abläufen kurz in die Bearbeitung 
und blockierst die Kiste nicht.

Jens R. schrieb:
> In einer letzten Antwort wurde mir geraten, Bibliotheken zu meiden, um
> etwas dazuzulernen. Das habe ich auch vor.
Mit Delay und digitalWrite etc. machst Du aber nix anderes.
Mach Dir mal den Spaß und setze mit digitalWrite einen Pin auf eins und 
gleich danach wieder auf null.
Schau Dir auf dem Oszi an wie lange das dauert, da bekommst Du eine 
Vorstellung davon wie unglaublich ineffizient das ist.

Ist oft egal, wenn die Kiste nur das tut was Du willst, aber Du willst 
ja lernen.

von Jens R. (homerqlb)


Bewertung
0 lesenswert
nicht lesenswert
Aha verstehe, den Notaus habe ich noch gar nicht drin, aber während des 
Hoch-und Ab-Tourens kann ich drauf rumkloppen wie ich will, es passiert 
nichts.
Aber leider verstehe ich "noch" null von flags u.s.w.
Danke für deine Hilfe.
Ich brauche erst noch alle Teile um richtig experimentieren zu können.
Und dann Schritt für Schritt weiter.
Ich finde das alles wirklich toll, wie man mit diesem Arduino als Laie 
auch schnell zu einem Ergebnis kommen kann.

von MaWin (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Jens R. schrieb:
>> Deine Erfahrung ? Ich dachte, du hast keine Erfahrung.
>> Ein Schrittmotor, der Schritte verliert, wurde falsch eingesetzt.
> Erfahrungen von meiner CNC Eigenbaufräse im Keller.

Örks, meine Erfahrung bisher lautet:
Du hast keine Ahnung vom Aufbau von Mechanik
und der Auslegung und Ansteuerung von Motoren.

Nein, Dinge funktionieren nicht einfach, wenn man sie beliebig falsch 
macht.

Jens R. schrieb:
>   pinMode(4; OUTPUT); //Endschalter
>   pinMode(5; OUTPUT); //Anfangsschalter

?!?

Jens R. schrieb:
>   digitalRead(StartPin)//Abfrage Starttaster
>   if (StartPin == HIGH) { //Wenn Starttaster gedrückt

?!?

Hier auch: Bei so wenig Aufmerksamkeit gegenüber der Lösung wird das 
nichts damit, Mikrocontroller damit zu programmieren was sie zu tun 
haben.

von Jens R. (homerqlb)


Bewertung
-1 lesenswert
nicht lesenswert
Ja, danke für den Hinweis,
die Schalter sind ja wohl INPUT.
Doing bei learning habe ich gelesen, wenn hier nur die Fehler aufgezählt 
werden, will ich eure wertvolle Zeit nicht weiter verschwenden und mache 
weiter, bis der letzte yC sein Leben ausgehaucht hat.
Ich danke für die Hilfe!

von M. K. (mkn)


Bewertung
0 lesenswert
nicht lesenswert
Jens R. schrieb:
> Aber leider verstehe ich "noch" null von flags u.s.w.

Ein Flag ist nur ein Bit.
Der Timer läuft ab und setzt das Bit.
Das ist das Zeichen, das Zeit xx abgelaufen ist.
Deine Auswertung startet sobald das Flag gesetzt ist und setzt es dabei 
zurück, damit wieder Zeitablauf signalisiert werden kann.

ISR bedeutet Interrupt Service Routine.
Der Timer im uC ist ein kleines Stück Hardware, das man über seine 
Register so einstellt, das es, unabhängig vom Rest des uC, in 
regelmäßigen Zeitabständen dem uC signalisiert, das er all seine 
Tätigkeiten unterbrechen und an einen bestimmten Programmbereich 
springen soll, an dem es Code abzuarbeiten gilt.
In der ISR macht man im allgemeinen so wenig wie möglich, um den 
normalen Programmablauf so wenig wie möglich zu blockieren.
Zieh Dir das Datenblatt des Microcontrollers der auf deinem arduino 
verbaut wurde. Da steht alles drin was Du wissen musst.

Die ganze Arduino Umgebung verschleiert ein wenig, das dahinter auch nur 
ein kleiner uC läuft, den man auch ohne die ganzen Arduino Libs beackern 
kann.
Ich kenne mich mit Arduino zu wenig aus um zu sagen welche Timer bereits 
belegt sind um z.B. delay() zu realisieren.

> Danke für deine Hilfe.
Du fragst vernünftig und bist bereit zuzuhören.
Da hilft man gern.

Lass Dich von dem rauen Ton nicht irritieren.
Frag einfach wenn Du was nicht verstehst und bleib freundlich als 
Fragesteller, auch wenns mal pampig wird.
Dann wird sich meist schon jemand finden der hilft.

Jens R. schrieb:
> will ich eure wertvolle Zeit nicht weiter verschwenden
Die verschwenden wir hier ja ganz freiwillig.

von Jens R. (homerqlb)


Bewertung
0 lesenswert
nicht lesenswert
Ich habe mir den Simulator for Arduino von Virtronics geladen und meinen 
Code simuliert.
Die Fehler habe ich beseitigt, weiß jemand zufällig, wie man einen 
Tastendruck (input) da simuliert?
Oder gibt es da bessere Simulatoren?

von Jens R. (homerqlb)


Bewertung
-1 lesenswert
nicht lesenswert
M. K. schrieb:
> Ein Flag ist nur ein Bit.
> Der Timer läuft ab und setzt das Bit.
> Das ist das Zeichen, das Zeit xx abgelaufen ist.
> Deine Auswertung startet sobald das Flag gesetzt ist und setzt es dabei
> zurück, damit wieder Zeitablauf signalisiert werden kann.
>
> ISR bedeutet Interrupt Service Routine.
> Der Timer im uC ist ein kleines Stück Hardware, das man über seine
> Register so einstellt, das es, unabhängig vom Rest des uC, in
> regelmäßigen Zeitabständen dem uC signalisiert, das er all seine
> Tätigkeiten unterbrechen und an einen bestimmten Programmbereich
> springen soll, an dem es Code abzuarbeiten gilt.
> In der ISR macht man im allgemeinen so wenig wie möglich, um den
> normalen Programmablauf so wenig wie möglich zu blockieren.
> Zieh Dir das Datenblatt des Microcontrollers der auf deinem arduino
> verbaut wurde. Da steht alles drin was Du wissen musst.

Ich ahne ungefähr, worauf du hinaus willst.
In so tiefe Gründe will ich dann doch nicht hinabtauchen.
Trotzdem werde ich wahrscheinlich bald vor einem Problem stehen:
Momentan bin ich mit meinem Code so weit fertig. Die Simulation läuft 
prächtig und macht alles richtig. Mit Nano hatte ich so meine 
Verbindungsschwierigkeiten (billige China-Büchse), habe den Code aber 
erfolgreich draufgespielt und nur mit LED`s mal getestet.
Jetzt habe ich folgende Idee:
Ich möchte den BL-Motor über den Fahrtenregler direkt per ESC 
ansteueren.
programmtechnischnisch ist das kein Problem. Anschließend läuft der 
Schrittmotor in einer Dauerschleife durch bis zum Endschalter. Dabei muß 
der Fahrtenregler, denke ich, parallel sein 2ms-Signal 
(Highspeed)erhalten sonst fällt er zurück?! Während des delay im 
Schrittmotortiming pausiert der Prozessor aber. Hast du einen Vorschlag, 
wie man das lösen kann?
Hier mein derzeitiger Code:
int DirPin = 3; //Dir Schrittmotor
int StepPin = 4; //Step Schrittmotor
int EndPin = 5; //Endschalter
int AnfPin = 6; //Anfangsschalter
int StartPin = 7; //Starttaster
int MotorSpeedPin = 2; //Motordrehzahl
int Step = 100; //Step pro Sek
int ESCMax = 2000; //max. Drehzahl Sägenmotor (2000µs)
int ESCPause = 20000; //Pause Motordrehzahl (20000µs)
void setup() {
  pinMode (2, OUTPUT); //Motorspeed
  pinMode (3, OUTPUT); //Dir Schrittmotor
  pinMode (4, OUTPUT); //Step Schrittmotor
  pinMode (5, INPUT_PULLUP); //Endschalter
  pinMode (6, INPUT_PULLUP); //Anfangsschalter
  pinMode (7, INPUT_PULLUP); //Starttaster

}

void loop() {
  //digitalWrite(StartPin, HIGH);
  if (digitalRead(StartPin) == LOW) { //Wenn Starttaster gedrückt
    for (int Speed = 0; Speed <= ESCMax; Speed++) {
      digitalWrite(MotorSpeedPin, HIGH);
      delayMicroseconds(Speed);
      digitalWrite(MotorSpeedPin, LOW);
      delayMicroseconds(ESCPause);
    }
    digitalWrite(DirPin, HIGH); //Richtung Schrittmotor
    //digitalWrite(EndPin, HIGH);
    while (digitalRead(EndPin) == HIGH) { //Schleife solange Endschalter micht geschaltet

      digitalWrite(StepPin, HIGH); //Signal Schrittmotor
      delay(Step); //Pausenlänge für Geschwindigkeit
      digitalWrite(StepPin, LOW); //Signal Schrittmotor
      delay(Step); //Pausenlänge für Geschwindigkeit
    }
    for (int Speed = 2000; ESCMax <= 0; Speed--) {
      digitalWrite(MotorSpeedPin, HIGH);
      delayMicroseconds(Speed);
      digitalWrite(MotorSpeedPin, LOW);
      delayMicroseconds(ESCPause);
    }
      digitalWrite(DirPin, LOW); //Richtungsumkehr Schrittmotor
      //digitalWrite(AnfPin, HIGH);
      while (digitalRead(AnfPin) == HIGH) { //Schleife solange Anfangsschalter micht geschaltet
        //Hier soll noch die Beschleunigung rein
        digitalWrite(StepPin, HIGH); //Signal Schrittmotor
        delay(Step); //Pausenlänge für Geschwindigkeit
        digitalWrite(StepPin, LOW); //Signal Schrittmotor
        delay(Step); //Pausenlänge für Geschwindigkeit
      }
    }
  }


von Johannes S. (jojos)


Bewertung
0 lesenswert
nicht lesenswert
State machine, das Stichwort hatte ich schonmal genannt.

von Jens R. (homerqlb)


Bewertung
-1 lesenswert
nicht lesenswert
Johannes S. schrieb:
> State machine, das Stichwort hatte ich schonmal genannt.

Ja wie löst das jetzt das Problem der Parallelabarbeitung 
(ESC/Schrittmotor)?
Ich habe schon wirklich sehr viel gelesen, das ist in der kurzen Zeit 
aber schon heftig und für mich schwer zu verstehen.
Ich benutze die Arduino Referenz als Quelle für den Code.
In der englischen Version habe ich mal etwas über eine Yield Funktion 
gelesen, die irgendwie in der Delay-Zeit etwas abarbeiten kann.
Ich wäre über weiterführende Tipps sehr dankbar.

von Alles schon da (Gast)


Bewertung
0 lesenswert
nicht lesenswert
M. K. schrieb:
> Ich schreibe mir für sowas eine Timer ISR die alle xx ms ein flag setzt.

Wenn man Arduino verwendet, kann man direkt den sowieso für millis() 
laufenden Timer verwenden und sich z.B. per TIMER0_COMPA Interrupt dort 
einklinken.
https://learn.adafruit.com/multi-tasking-the-arduino-part-2/timers

Oder man prüft den Rückgabewert von millis() auf Änderung gegenüber dem 
vorherigen Aufruf ;-)

von Jens R. (homerqlb)


Bewertung
-1 lesenswert
nicht lesenswert
Alles schon da schrieb:
> M. K. schrieb:
>> Ich schreibe mir für sowas eine Timer ISR die alle xx ms ein flag setzt.
>
> Wenn man Arduino verwendet, kann man direkt den sowieso für millis()
> laufenden Timer verwenden und sich z.B. per TIMER0_COMPA Interrupt dort
> einklinken.
> https://learn.adafruit.com/multi-tasking-the-arduino-part-2/timers
>
> Oder man prüft den Rückgabewert von millis() auf Änderung gegenüber dem
> vorherigen Aufruf ;-)

Oh ja harter Tobak, für mich jedenfalls, da brauche ich Jahre, das zu 
verstehen.
Vielleicht splitte ich die delays für den Schriitmmotor dann doch lieber 
auf. Ich habe gelesen, dass der ESC eine Aktualisierung von 50ms 
braucht, da muß ich mit den einzelnen delays für den Schrittmotor 
drunter bleiben und aktualisiere den ESC dann mehrmals pro 
Schrittmotor-Takt.
Nicht gerade elegant, aber ich denke, das kriege ich so auch hin.

von Jens R. (homerqlb)


Bewertung
0 lesenswert
nicht lesenswert
Ich hab mir gerade nochmal die "millis" Funktion verinnerlicht, das wird 
die Lösung sein.
"millis" Zeit auslesen und in Variable merken,
anstatt delay eine Schleife, mit Abfrage ob die "millis"Variable um 
festgelegten Wert erreicht hat, dann folgende Aktion.
In der Schleife kann ich dann belibigen Code ausführen, z. B. den ESC 
aktualisieren.
Ich hoffe, ich habe das so richtig verstanden.

von Johannes S. (jojos)


Bewertung
0 lesenswert
nicht lesenswert
hier hatte ich mal ein Beispiel für eine state machine genannt. Es geht 
nur ums Prinzip, nicht jetzt hier das konkrete Problem.
Beitrag "Re: Schrittmotor"

Also das Programm rennt immer im Kreis und guckt was aktuell zu tun ist 
(die case im switch statement). Wenn ein Schritt fertig kann auf den 
nächsten oder einen anderen geschaltet werden. Den cases kann man auch 
Namen geben um das übersichtlicher zu machen.
So 'hängt' das Programm nicht in einem Schritt, sondern ist immer bereit 
auf Ereignisse zu reagieren. Auch wenn dir dein Programm jetzt einfacher 
erscheint, so ein switch-case ist einfacher zu testen.

: Bearbeitet durch User
von Jens R. (homerqlb)


Bewertung
0 lesenswert
nicht lesenswert
O.K.
Ich werde mir das nochmal ansehen mit den switch-case.
Danke erstmal.

von Jens R. (homerqlb)


Bewertung
-1 lesenswert
nicht lesenswert
Johannes S. schrieb:
> hier hatte ich mal ein Beispiel für eine state machine genannt. Es geht
> nur ums Prinzip, nicht jetzt hier das konkrete Problem.
> Beitrag "Re: Schrittmotor"
>
> Also das Programm rennt immer im Kreis und guckt was aktuell zu tun ist
> (die case im switch statement). Wenn ein Schritt fertig kann auf den
> nächsten oder einen anderen geschaltet werden. Den cases kann man auch
> Namen geben um das übersichtlicher zu machen.
> So 'hängt' das Programm nicht in einem Schritt, sondern ist immer bereit
> auf Ereignisse zu reagieren. Auch wenn dir dein Programm jetzt einfacher
> erscheint, so ein switch-case ist einfacher zu testen.

Ich habe das jetzt erst mal so gelöst. Ich hoffe es funktioniert.
Die Simulationmit TinkerCAD ist ein bisschen einfach aber besser als gar 
nichts.
digitalWrite(DirPin, HIGH); //Richtung Schrittmotor
  while (digitalRead(EndPin) == HIGH) { //Schleife solange Endschalter nicht geschaltet
     digitalWrite(StepPin, HIGH); //Signal Schrittmotor
      Time = millis(); //aktuelle Laufzeit in Time
        StepTime = Time + Step; //Zeit für nächstes Schrittmotorsignal berechnen
          while (StepTime > Time) { //Schleife Signal ESC
            digitalWrite(MotorSpeedPin, HIGH);
            delayMicroseconds(ESCSpeed);
            digitalWrite(MotorSpeedPin, LOW);
            delayMicroseconds(ESCPause);
            Time = millis(); //aktuelle Laufzeit in Time
          }  
digitalWrite(StepPin, LOW); //Signal Schrittmotor
        Time = millis(); //aktuelle Laufzeit in Time
        StepTime = Time + Step; //Zeit für nächstes Schrittmotorsignal berechnen
          while (StepTime > Time) { //Schleife Signal für ESC
            digitalWrite(MotorSpeedPin, HIGH);
            delayMicroseconds(ESCSpeed);
            digitalWrite(MotorSpeedPin, LOW);
            delayMicroseconds(ESCPause);
            Time = millis(); //aktuelle Laufzeit in Time
          }
    }
Eine Frage zur switch Funktion.
in der switch Abfrage wird ja nur eine Funktion, eben die, die die 
Bedingung erfüllt, ausgeführt. Das break steigt dann aus, also ist diese 
Funktion keine Scleife, wenn ich richtig verstanden habe. so muß ich die 
switch Funktion also noch in eine Dauerschleife legen?

von Johannes S. (jojos)


Bewertung
0 lesenswert
nicht lesenswert
Jens R. schrieb:
> so muß ich die switch Funktion also noch in eine Dauerschleife legen?

Ja, richtig. Aber es blockiert aber nicht an den Delays.

von Jens R. (homerqlb)


Bewertung
-2 lesenswert
nicht lesenswert
Johannes S. schrieb:
> Jens R. schrieb:
>> so muß ich die switch Funktion also noch in eine Dauerschleife legen?
>
> Ja, richtig. Aber es blockiert aber nicht an den Delays.

Ah ja. Ostern hab ich Zeit zum probieren.
Die delays sind ja auch immer noch drin.

von M. K. (mkn)


Bewertung
2 lesenswert
nicht lesenswert
Jens R. schrieb:
> Ja wie löst das jetzt das Problem der Parallelabarbeitung

Tja, das ist genau der Teil in den Du nicht so tief einsteigen willst.
Wasch mir den Pelz, aber mach mich nicht nass...

Entweder löst Du Dich von dem Delay Gemurkse und machst das richtig, 
oder Du lebst mit dem Gemurkse.
Aber die Frage einfach nochmal stellen weil die Antwort nicht genehm 
war, funktioniert nicht.

von Jens R. (homerqlb)


Bewertung
0 lesenswert
nicht lesenswert
M. K. schrieb:
> Entweder löst Du Dich von dem Delay Gemurkse und machst das richtig,
> oder Du lebst mit dem Gemurkse.
> Aber die Frage einfach nochmal stellen weil die Antwort nicht genehm
> war, funktioniert nicht.

Na wenigstens hab ich noch deine Aufmerksamkeit.
In einem Punkt hast du recht, ich und auch nur ich werde mit dem 
Gemurkse leben müssen.
Dein letzter Beitrag war genauso unfreundlich, aber hilfreicher.
Wenn das ganze erst mal läuft, kräht kein Hahn mehr danach, ob delay 
oder nicht delay.
Im Falle eines Scheiterns mache ich ein Video von der abbrennenden 
Maschine und stell es hier ein. Dann kommt deine Zeit, dich mit 
erhobenen Zeigefinger hinzuzustellen und zu sagen "Ich hab ja gleich 
gesagt, der hat von nichts eine Ahnung!"
Ich hoffe auf weiter Beiträge, vielleicht auch mal wieder mit 
hilfreichem Inhalt, so wie die der anderen Beteiligten.

von sid (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Wolfgang schrieb:
> Ein Schrittmotor läuft nicht einfach los
> und fährt dann bis zu einem Endschalter. Ein Schrittmotor muss jeden
> einzelnen Schritt gesagt bekommen und die Anzahl der Schritte bestimmt
> den Fahrweg. Da braucht man keinen Endschalter. Es reicht eine
> Referenzmarke, an der sich der µC orientieren kann.

Nunja und als Referenzmarke eignet sich besonders gut ein Endschalter ;)

Ausserdem kann man wenn man in der Tat zwei Endschalter benutzt und 
auswertet,
eine einfache while loop ohne Schrittzähler schreiben
gehen wir mal von NC schaltern aus:
wäre das
in pseudo code in etwa:
[code]
while(endschalter_ende) schrittmotor.step(fwd);
delay(pause);
while(endschalter_start) schrittmotor.step(rwd);
delay(pause);
[code]

banal, gell?

'sid

von Jens R. (homerqlb)


Bewertung
0 lesenswert
nicht lesenswert
sid schrieb:
> in pseudo code in etwa:
> [code]
> while(endschalter_ende) schrittmotor.step(fwd);
> delay(pause);
> while(endschalter_start) schrittmotor.step(rwd);
> delay(pause);
> [code]
>
> banal, gell?

Genau so habe ich es umgesetzt.

von Jens R. (homerqlb)


Bewertung
0 lesenswert
nicht lesenswert
Eine Frage zu switch-case.
Ich frage die aktuelle Laufzeit ab, das ist die Vergleichsvariable im 
switch
zur Laufzeit addiere ich die Taktzeit um die Bedingung für diesen case 
festzulegen und speichere die in einer Variable.
Die Variable kann ich laut Referenz aber nicht im case eintragen.
Bleibt mir nur die Möglichkeit über return der Variable einen Zahlenwert 
zuzuweisen?

von Jens R. (homerqlb)


Bewertung
0 lesenswert
nicht lesenswert
Hier mein Code:
digitalWrite(DirPin, HIGH); //Richtung Schrittmotor
Time = millis(); //aktuelle Laufzeit in Time
StepTime = Time + Step; //Zeit für nächstes Schrittmotorsignal berechnen
  while (digitalRead(EndPin) == HIGH) { //Schleife solange Endschalter nicht geschaltet
     Time = millis(); //aktuelle Laufzeit in Time
         switch(Time){



         case StepTime: //Erzeugt einen Fehler



            if (StepPin==HIGH){
            digitalWrite(StepPin, LOW); //Signal Schrittmotor LOW wenn HIGH
            }
            else{
            digitalWrite(StepPin, HIGH); //Signal Schrittmotor HIGH wenn LOW
            }
            Time = millis(); //aktuelle Laufzeit in Time
            StepTime = Time + Step; //Zeit für nächstes Schrittmotorsignal berechnen
            break;
         default:
         digitalWrite(MotorSpeedPin, HIGH);
            delayMicroseconds(ESCSpeed);
            digitalWrite(MotorSpeedPin, LOW);
            delayMicroseconds(ESCPause);
            break;
        }

von Johannes S. (jojos)


Bewertung
0 lesenswert
nicht lesenswert
So klappt das nicht, in switch() muss eine Variable rein die definiert 
gesetzt wird. Und dann landet man beim Aufruf in dem passenden case.
Also einfaches Beispiel Ampel: switch(Farbe) und case Rot/gelb/Grün 
setzt den entsprechenden Ausgang.
Um eine Schrittkette zu bauen also die einzelnen Schritte definieren und 
dann in jedem Schritt (case) weiterschalten wenn eine Bedingung erfüllt 
ist.

von M. K. (mkn)


Bewertung
0 lesenswert
nicht lesenswert
Jens R. schrieb:
> Dein letzter Beitrag war genauso unfreundlich,

Nein, er war ehrlich.
Du hattes gefragt wie Du schnelle Reaktionen in Deinem Zeitablauf 
integrieren kannst.
Du würdest ja gerne dazulernen und deswegen bereit sein die LIBs nicht 
zu verwenden.
Darauf haben ich und andere geantwortet.
Du hast erkannt, das das eben nicht mal so mit drei Zeilen gemacht ist 
und hast entschieden nicht nur bei den LIBs zu bleiben, sondern die auch 
noch auf die einfachst mögliche Art einzusetzen..
Das steht Dir zu, ist ja Dein Projekt.

Nun hast Du aber natürlich immer noch die gleichen Probleme, weil Du es 
ja weiterhin auf die gleiche Art tust, und stellst einfach nochmal die 
Frage wie man die Probleme loswird.

Die Antwort ist aber die gleiche wie zuvor und genau darauf habe ich 
Dich hingewiesen.
Nun ist es aber von mir unfreundlich Dir unangenehme Wahrheiten zu 
sagen, von Dir aber nicht, die gegebenen Antworten zu ignorieren?

Das widerum macht Dich zu einem der üblichen MC.net Fragesteller und die 
verlieren meine Aufmerksamkeit.

von Jens R. (homerqlb)


Bewertung
0 lesenswert
nicht lesenswert
M. K. schrieb:
> Nein, er war ehrlich.

O.K. ich versteh deine Sprache offensichtlich nicht, aber dass dieses 
Forum nichts für Zartbesaitete ist, wurde mir ja schon angekündigt.


M. K. schrieb:
> Nun hast Du aber natürlich immer noch die gleichen Probleme, weil Du es
> ja weiterhin auf die gleiche Art tust, und stellst einfach nochmal die
> Frage wie man die Probleme loswird.

Leider weist du mich nur darauf hin, dass ich alles falsch mache.
Ein Schubs in die richtige Richtung z.B. wäre nicht schlecht.
Ich wurde animiert, es mit der switch-Case Funktion zu probieren, ich 
denke, ich habe verstanden wozu sie gut ist, hänge aber an der Umsetzung 
fest, wie man an meinem letzten switch-Gemurkse erkennen kann.
Du bist doch Mitglied seit 2012 ich seit 2 Wochen, genau so lange 
beschäftige ich mich mit der Programmierei um den Arudino.
Vielleicht könntest du von deiner reichlichen Erfahrung etwas an mich 
weitergeben?

M. K. schrieb:
> Das widerum macht Dich zu einem der üblichen MC.net Fragesteller und die
> verlieren meine Aufmerksamkeit.

Das wäre das letzte, was ich erreichen wollte!

von Jens R. (homerqlb)


Bewertung
0 lesenswert
nicht lesenswert
Johannes S. schrieb:
> So klappt das nicht, in switch() muss eine Variable rein die definiert
> gesetzt wird. Und dann landet man beim Aufruf in dem passenden case.
> Also einfaches Beispiel Ampel: switch(Farbe) und case Rot/gelb/Grün
> setzt den entsprechenden Ausgang.
> Um eine Schrittkette zu bauen also die einzelnen Schritte definieren und
> dann in jedem Schritt (case) weiterschalten wenn eine Bedingung erfüllt
> ist.

Bitte entschuldige, ich habe deinen Beitrag glatt übersehen.
Danke für die Antwort.
Ich bin da wohl einem Mißverständnis unterlegen.
Hier der korrigierte Code, der zumindest keinen Fehler wirft.
igitalWrite(DirPin, HIGH); //Richtung Schrittmotor
Time = millis(); //aktuelle Laufzeit in Time
StepTime = Time + Step; //Zeit für nächstes Schrittmotorsignal berechnen
  while (digitalRead(EndPin) == HIGH) { //Schleife solange Endschalter nicht geschaltet
    Time = millis(); //aktuelle Laufzeit in Time
    if (Time==StepTime){Zustand =1;} //Zustand wird 1 gesetzt, wenn die akt.Zeit gleich der berechneten Zeit für das Schrittmotorsignal ist
       switch(Zustand){
          case 1:
            if (StepPin==HIGH){
              digitalWrite(StepPin, LOW); //Signal Schrittmotor LOW wenn HIGH
              }
              else{
              digitalWrite(StepPin, HIGH); //Signal Schrittmotor HIGH wenn LOW
              }
              Time = millis(); //aktuelle Laufzeit in Time
              StepTime = Time + Step; //Zeit für nächstes Schrittmotorsignal berechnen
              break;
          default:
          digitalWrite(MotorSpeedPin, HIGH);
            delayMicroseconds(ESCSpeed);
            digitalWrite(MotorSpeedPin, LOW);
            delayMicroseconds(ESCPause);
            break;
Allerdings stellt sich mir die Frage, ob 2 Zustände wirklich den Switch 
benötigen, wie man sieht gibt es nicht viel zu entscheiden.
Dieser Code bedient ja auch nur den Zustand Endschalter HIGH.
Wenn ich alle möglichen Zustände ansehe, dann kommt mir das Ganze 
plausibel vor. Dann werde ich mein Gerüst mal wieder abreißen und neu 
aufbauen.
Bis dahin kann ich ja schon mal die einzelnen Codeschnipsel für 
Schrittmotoransteuerung, BL-Motorsteuerung ausprobieren.
Danke für den Stubser in die richtige Richtung.

von M. K. (mkn)


Bewertung
0 lesenswert
nicht lesenswert
Jens R. schrieb:
> Ein Schubs in die richtige Richtung z.B. wäre nicht schlecht.
Beitrag "Re: Ansteuerung eines Schrittmotors mit 2 Endschaltern"

von Jens R. (homerqlb)


Bewertung
0 lesenswert
nicht lesenswert
Bin momentan schwer am Programmieren, sieht auch schon vielversprechend 
aus leider noch ohne switch-case.
In der Simulation läuft es auch schon ganz gut.
Jetzt habe ich den Ardunino mit einem einfachen Programm für die 
Steuerung des ESC des BL-Motors geladen und da gibt es gleich ein großes 
Problem. Der Motor läuft kurz an, und wieder aus. nicht wie 
programmiert.
Nun geh ich der Sache erstmal auf den Grund.
Dann teste ich den Schrittmotor mit einem einfachen Programm.
Dann weiter mit Programmieren. Mir qualmt schon der Kopf!

von Johannes S. (jojos)


Bewertung
-1 lesenswert
nicht lesenswert
Für den BL Motor über ESC hat Arduino etwas fertiges: die Servo Library. 
Teste mal das Beispiele/Servo/Sweep.

Servo erledigt die schnelle Pulsausgabe im Hintergrund per Timer und 
Interrupt, das läuft also vor sich hin während du dich um die 
Schrittkette kümmern kannst. Mit dem Hardwaretimer ist das präziser, in 
SW hast du einen Jitter im Signal. Wenn ein Servo angeschlossen wäre, 
dann würdest ein zittern sehen.

Das main bzw. die Arduino loop kann dann nach dem alten EVA Prinzip 
arbeiten: Eingabe, Verarbeiten, Ausgabe.
Eingabe ist ein Unterprogramm checkInputs(), das liest alles Taster ein 
und macht die Flankenerkennung und erzeugt Ereignisse. So ist das 
Weiterverarbeiten einfacher. Ein Button Start setzt dann die 
Schrittkette auf den Startschritt.

Für die Schrittkette überlegtst du dir was jeweils passieren soll:
 0 stateIdle : Ruhezustand, keine Änderungen
 1 stateMoveHome : Säge ausschalten. wenn nicht in Hompos, Schlitten in 
Homeposition fahren auslösen. wenn in Homepos, state++
 2 stateSawStart : Sägemotor einschalten (spin up kann man später noch 
einbauen). Setzte Wartezeit. state++
 3 stateMoveEnd: wenn nicht in Endpos, Fahrt in Endpos auslösen sonst 
state++

usw.

von Jens R. (homerqlb)


Bewertung
0 lesenswert
nicht lesenswert
Johannes S. schrieb:
> Für den BL Motor über ESC hat Arduino etwas fertiges: die Servo Library.
> Teste mal das Beispiele/Servo/Sweep.

Das ist nicht so einfach mit dem BL-Motor.
Das Problem liegt in der Initialisierung des Fahrtenreglers, der ja noch 
zwischen Motor und Arduino hängt.
Aber ich habe eine Bibliothek gefunden, womit es funktionieren könnte.
Somit verabschiede ich mich jetzt von der Idee, alles selbst 
programmieren zu wollen. Es wird ja sowieso alles Murks, aber vielleicht 
funktionierender Murks.

Johannes S. schrieb:
> Für die Schrittkette überlegtst du dir was jeweils passieren soll:
>  0 stateIdle : Ruhezustand, keine Änderungen
>  1 stateMoveHome : Säge ausschalten. wenn nicht in Hompos, Schlitten in
> Homeposition fahren auslösen. wenn in Homepos, state++
>  2 stateSawStart : Sägemotor einschalten (spin up kann man später noch
> einbauen). Setzte Wartezeit. state++
>  3 stateMoveEnd: wenn nicht in Endpos, Fahrt in Endpos auslösen sonst
> state++

Das sind dann die case Schritte?
Ich muß aber in Schleifen erst die einzelnen Variablen mit einem Wert 
belegen, sodaß im switch das entsprechende case ausgeführt wird.
Sehe ich das richtig so?

von Michael B. (laberkopp)


Bewertung
-1 lesenswert
nicht lesenswert
Jens R. schrieb:
> Ich frage die aktuelle Laufzeit ab, das ist die Vergleichsvariable im
> switch

Nein.

Die variable in switch ist der aktuelle BewegungsZustand, steht ja wohl 
auch in den case-Kommentaren deutlich drin.

Johannes S. schrieb:
> Für den BL Motor über ESC

Er möchte aber einen Schrittmotor ohne ESC.

von Johannes S. (jojos)


Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Michael B. schrieb:
> Er möchte aber einen Schrittmotor ohne ESC.

er hat zwei Motoren, einen SM der einen Schlitten mit Säge antreibt und 
einen BL mit ESC der das Sägeblatt antreibt. Wenn es noch so ist.

Gegen die Corona Langeweile habe ich mal ein Beispiel für den Nano 
gemacht, so wie ich es machen würde.
Die Schrittkette wird über einen Button an D2 (gegen Masse) gestartet. 
An D3 ist ein Button mit Stopfunktion.
Am Serial Monitor wird die Änderung des Zustands ausgegeben. Das Servo 
ist hier noch nicht drin, kann aber über die Servo Klasse einfach 
eingebaut werden.
Arduino ist nicht meine Lieblingsplattform, eventuelle Unschärfen sind 
gut möglich.

von Johannes S. (jojos)


Bewertung
0 lesenswert
nicht lesenswert
Jens R. schrieb:
> Das Problem liegt in der Initialisierung des Fahrtenreglers, der ja noch
> zwischen Motor und Arduino hängt.

Die muss man aber üblicherweise nur einmal machen, der Fahrtenregler 
speichert dann die min/max Werte. Das muss also nicht unbedingt in den 
gleichen Code mit rein, geht aber auch.
Da kann man auch den Serial Monitor nutzen um zusätzliche Kommandos zu 
schicken um nicht alles auf Tasten legen zu müssen. Dafür kann man auch 
übergeordnet wieder ein switch/case machen um verschiedene Programme 
ablaufen zu lassen und nicht alles in eine riesige Schrittkette 
einzufügen.

von sid (Gast)


Bewertung
0 lesenswert
nicht lesenswert
millis vergleichen kann in die Hose gehen und schon deswegen ist der 
switchcase mMn der falsche weg.
zunächst..
Du kannst einen Pin mit sich selbst vergleichen
statt
 if (StepPin==HIGH){
              digitalWrite(StepPin, LOW); //Signal Schrittmotor LOW wenn HIGH
              }
              else{
              digitalWrite(StepPin, HIGH); //Signal Schrittmotor HIGH wenn LOW
              }
reicht
digitalWrite(StepPin,!digitalRead(StepPin)); //liest StepPin, und setzt ihn negiert neu

wenn Du millis vergleichen willst sei darauf vorbereitet,
daß der gelesene Wert vom Erwarteten abweichen kann.
ich weiss nicht wie lange die Säge laufen soll
eventuell rennst du sogar in einen timer overflow;
deswegen sei damit extra Vorsichtig..

'sid

von Jens R. (homerqlb)


Bewertung
0 lesenswert
nicht lesenswert
sid schrieb:
> Du kannst einen Pin mit sich selbst vergleichen
> statt

Danke guter Tipp

sid schrieb:
> wenn Du millis vergleichen willst sei darauf vorbereitet,
> daß der gelesene Wert vom Erwarteten abweichen kann.
> ich weiss nicht wie lange die Säge laufen soll
> eventuell rennst du sogar in einen timer overflow;
> deswegen sei damit extra Vorsichtig..

Deswegen hätte ich >=/<= im Vergleich genommen, um den richtigen Moment 
nicht zu verpassen, wenn es das Problem darstellen sollte. Eine 
zeitliche Toleranz sollte kein Problem darstellen.
Sonst stecke ich in einem Dilemma, denn delay blockiert nun mal die 
Abarbeitung.

von Jens R. (homerqlb)


Bewertung
0 lesenswert
nicht lesenswert
Johannes S. schrieb:
> Die muss man aber üblicherweise nur einmal machen, der Fahrtenregler
> speichert dann die min/max Werte. Das muss also nicht unbedingt in den
> gleichen Code mit rein, geht aber auch.

Ich habe eine Bibliothek ESC.h, damit funktioniert es jetzt.

von Jens R. (homerqlb)


Bewertung
0 lesenswert
nicht lesenswert
Johannes S. schrieb:
> er hat zwei Motoren, einen SM der einen Schlitten mit Säge antreibt und
> einen BL mit ESC der das Sägeblatt antreibt. Wenn es noch so ist.
>
> Gegen die Corona Langeweile habe ich mal ein Beispiel für den Nano
> gemacht, so wie ich es machen würde.

Ja so ist es:
Hier die Hardware
Ein BL-Motor für Säge mit Fahrtenregler (ESC-Eingang)
Ein Schrittmotor  mit Schrittmotorkarte A4988 (Sep/Dir-Eingang) für 
Hin-Her-Bewegung
Ein Taster Start/Stop
Ein Taster Enschalter
Ein Taster Anfangsschalter.
Hier die Befehlskette:
Starttaste gedrückt
1. BL-Motor starten
2. Wartezeit zum Hochtouren des BL-Motor
3. SM-Motor starten Richtung hin
4. Bei Taste Endsch. gedrückt SM-Motor anhalten und BL-Motor ausschalten
5. SM-Motor starten Richtung zurück
6. Bei Anfangssch. gedrückt SM-Motor abschalten
Schleifenende
An allen Positionen soll die Abarbeitung unterbrochen werden können, das 
heißt SM-Motor aus BL-Motor aus.
Für einen Neustart bei einer Unterbrechung sollte ganz am Anfang 
vielleicht noch die Anfangpos. angefahren werden.
So ist mein Grundkonzept.
In deinem Code finde ich die End/Anf.-Scahlter nicht.
Ein Relais wird nicht benötigt, da der BL-Motor über den ESC gestartet 
wird.

von Jens R. (homerqlb)


Bewertung
0 lesenswert
nicht lesenswert
Michael B. schrieb:
> Nein.
>
> Die variable in switch ist der aktuelle BewegungsZustand, steht ja wohl
> auch in den case-Kommentaren deutlich drin.

Ja danke, das habe ich jetzt kapiert.

von Hugo H. (hugohurtig1)


Bewertung
0 lesenswert
nicht lesenswert
tommy schrieb:
> Jens R. schrieb:
>> Erfahrungsgemäß kommt es bei Schrittmotoren zu Schrittverlusten, aus
>> unterschiedlichen Gründen.
>
> Das passiert nur Bastlern.

Das halte ich für ein Gerücht.

Dem hier vertraue ich: :-)

http://www.schrittmotor-blog.de/

Eine "Rampe" reduziert die Möglichkeit eines Schrittverlustes - kann 
diesen aber nicht gänzlich verhindern.

von Jens R. (homerqlb)


Bewertung
0 lesenswert
nicht lesenswert
Hugo H. schrieb:
> tommy schrieb:
>> Jens R. schrieb:
>>> Erfahrungsgemäß kommt es bei Schrittmotoren zu Schrittverlusten, aus
>>> unterschiedlichen Gründen.
>>
>> Das passiert nur Bastlern.
>
> Das halte ich für ein Gerücht.
>
> Dem hier vertraue ich: :-)
>
> http://www.schrittmotor-blog.de/
>
> Eine "Rampe" reduziert die Möglichkeit eines Schrittverlustes - kann
> diesen aber nicht gänzlich verhindern.

Danke für die Unterstützung, deshalb ja die Endschalter. Und die Rampe, 
damit die schwere Last in Fahrt kommt.

von Wolfgang (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Jens R. schrieb:
> Danke für die Unterstützung, deshalb ja die Endschalter. Und die Rampe,
> damit die schwere Last in Fahrt kommt.

Am Ende hast du das gleiche Problem. Nachdem der andere Endschalter 
angeschlagen hat, braucht man noch eine Rampe zum Abbremsen, d.h. nach 
Ansprechen des Endschalter muss noch genügend Spielraum für die 
Abbremsrampe sein. Abhängig von der Fahrgeschwindigkeit fährt der Motor 
immer ein Stück über die Endschalterposition hinaus.

Anders ausgedrückt: Mit dieser Vorgehensweise kann der Schrittmotor nie 
mit voller Fahrt in Richtung Endschalter fahren und dort anhalten.

von Johannes S. (jojos)


Bewertung
0 lesenswert
nicht lesenswert
Jens R. schrieb:
> In deinem Code finde ich die End/Anf.-Scahlter nicht.
> Ein Relais wird nicht benötigt, da der BL-Motor über den ESC gestartet
> wird.

Das sollte ja auch ein Muster sein und noch nicht die komplette Lösung. 
Es funktioniert soweit, habe ich auf dem Steckbrett getestet.
Endschalter sind weitere Eingänge die in checkInputs eingelesen werden, 
Flankenerkennung wie bei den Tasten ist bei denen nicht nötig. Die 
states enum muss erweitert werden und in processStateMachine() die 
entsprechenden Aktionen.
Das Servo Objekt liefert das Timing das für den ESC gleich ist, also 
kann man mit servo.write(speed) die Geschwindigkeit vom BL Motor 
einstellen.

von Jens R. (homerqlb)


Bewertung
0 lesenswert
nicht lesenswert
Johannes S. schrieb:
> Jens R. schrieb:
>> In deinem Code finde ich die End/Anf.-Scahlter nicht.
>> Ein Relais wird nicht benötigt, da der BL-Motor über den ESC gestartet
>> wird.
>
> Das sollte ja auch ein Muster sein und noch nicht die komplette Lösung.
> Es funktioniert soweit, habe ich auf dem Steckbrett getestet.
> Endschalter sind weitere Eingänge die in checkInputs eingelesen werden,
> Flankenerkennung wie bei den Tasten ist bei denen nicht nötig. Die
> states enum muss erweitert werden und in processStateMachine() die
> entsprechenden Aktionen.
> Das Servo Objekt liefert das Timing das für den ESC gleich ist, also
> kann man mit servo.write(speed) die Geschwindigkeit vom BL Motor
> einstellen.

Bitte nicht falsch verstehen, natürlich freut es mich, dass du bisher 
als einziger einen Code zusammengebastelt, äh programmiert hast.
Vielen Dank dafür. Ich bin schon am Lesen und versuche es zu verstehen.

von Jens R. (homerqlb)


Bewertung
0 lesenswert
nicht lesenswert
Wolfgang schrieb:
> Anders ausgedrückt: Mit dieser Vorgehensweise kann der Schrittmotor nie
> mit voller Fahrt in Richtung Endschalter fahren und dort anhalten.

Ja, da lasse ich mir dann etwas Luft, wie gesagt ich muß hier nicht 
hochgenau positionieren!

von Johannes S. (jojos)


Bewertung
0 lesenswert
nicht lesenswert
Ich habe mich auch bemüht ein paar Kommentare reinzuschreiben :)
Den Anfang habe ich ja mitverfolgt, da warst du noch bei einer Steuerung 
aus Relais und Verzögerungsschaltern. Das man das nicht alles sofort 
versteht wenn man mit µC anfängt ist ok, dafür bist du schon lernfähiger 
als einige andere die hier im Forum aufschlagen. Also nicht entmutigen 
lassen und weiter so.
Das Serial.print() ist zwar nicht so schön wie ein Debugger um etwas zu 
verfolgen, hilft hier aber auch.

von Jens R. (homerqlb)


Bewertung
0 lesenswert
nicht lesenswert
Johannes S. schrieb:
> Ich habe mich auch bemüht ein paar Kommentare reinzuschreiben :)
> Den Anfang habe ich ja mitverfolgt, da warst du noch bei einer Steuerung
> aus Relais und Verzögerungsschaltern. Das man das nicht alles sofort
> versteht wenn man mit µC anfängt ist ok, dafür bist du schon lernfähiger
> als einige andere die hier im Forum aufschlagen. Also nicht entmutigen
> lassen und weiter so.
> Das Serial.print() ist zwar nicht so schön wie ein Debugger um etwas zu
> verfolgen, hilft hier aber auch.

Nun ja, mein Projekt ist und bleibt eigentlich die Gehrungssäge.
Als ich mit der Idee anfing, habe ich mir zuerst die Säge konstruiert 
und gebaut.
Also "Steuerung" war der BL-Motor für die Säge ein DC-Motor für den 
Vortrieb und Endschalter, die per Relais die Richtung umschalten, also 
nix mit großartiger Elektronik, gedacht.
Dann gab es schon Probleme mit der Logik und den Relais.
Das Ganze schien im Aufwand aus dem Ruder zu laufen.
Ich bekam den Tipp, das mit dem Arduino zu lösen, ich hatte bis dato 
noch geglaubt, dass man solche Chips noch "brennen" muß, also nichts für 
Hobby.
Auch preislich war ich überrascht.
Da ich schon mal etwas vom "Programmieren" gehört habe, dachte ich, das 
kiegst du auch hin.
Zwangsläufig muß ich mich auch mit der "Arduino-Sprache" 
auseinandersetzen.
Dr. Google hilft da ungemein, beantwortet aber deine Fragen nicht.
Deshalb bin ich hier gelandet.

von Jens R. (homerqlb)


Bewertung
0 lesenswert
nicht lesenswert
Ich möchte jetzt nochmal neu anfangen mit dem Programmieren.
Aus meiner Arbeit kenn ich das Programmieren so:
Ich schreibe alle Dinge, die sich wiederholen in ein label nach dem 
Programmende.
Aus dem Hauptprogramm heraus rufe ich die label bei Bedarf auf.
das geschieht mit "call label", dadurch gibt es einen Rücksprung hinter 
die Aufrufstelle.
In der Arduino-Referenz finde ich nur den goto-Befehl, kein Rücksprung, 
nicht außerhalb der Schleife.
Klar kann man das mit wiederum goto-Befehlen lösen, ist aber sehr 
aufwendig.
Ich möchte das so, wie es schon mal einer mit der Steuererklärung auf 
dem Bierdeckel machen wollte, schön klein und dadurch übersichtich (für 
mich).
Seht ihr da eine Möglichkeit.
Nicht gleich wettern, mit dem switch-case kann ich mich noch nicht 
anfreunden, da ich da mehrere Probleme sehe:
Wenn ich das richtig verstanden habe, bekommt die switch-Variable einen 
Wert zugewiesen, dann ein Sprung zum Vergleichswert im case und den Code 
dort ausführen. Anschließend geht`s nach break hinter dem switch-Befehl 
weiter.
Jetzt kann ich jedem case eine Funktion zuweisen. Z.B. BL-Motor an, 
BL-Motor aus, Schrittmotor vorwärts, Schrittmotor rückwärts, Starttaste 
gedrückt, u.s.w.
Ich muß aber jedesmal vorher die switch-Variable entsprechend zuweisen.
Starttaste hat aber z.B. 2 Funktionen.
Auch wird immer nur eine Funktion oder mehrere hintereinander, aber in 
der Reihenfolge ausgeführt.
Oder ich gebe jeder möglich Konstellation einen case und habe ein 
Programm, das nicht auf den Chip passt.
Einen Rücksprung zu Variablendefinition gibt es auch nicht.

von STK500-Besitzer (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Jens R. schrieb:
> In der Arduino-Referenz finde ich nur den goto-Befehl, kein Rücksprung,
> nicht außerhalb der Schleife.

Weil eigentlich niemand goto braucht.

Wie wäre es denn, wenn du mal die einzelnen Funktionen, die dein 
Programm erfüllen soll, als Blöcke definierst und dir auf ein Blatt 
Papier zeichnest?!

Programmieren ist nicht, alles in einer bestimmten Programmiersprache 
einzuhacken, sondern das Zerlegen eines Problems in Einzellösungen, die 
dann in Algorithmen übersetzt werden, die dann wiederum in einer 
beliebigen Programmiersprache dem Computer verständlich gemacht werden.

von Wolfgang (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Jens R. schrieb:
> Klar kann man das mit wiederum goto-Befehlen lösen, ist aber sehr
> aufwendig.

Denke in Anweisungsblöcken und Entscheidungen, gut darstellbar mit 
Nassi-Shneiderman Diagrammen. Dann brauchst du keine goto-Befehle.
https://de.wikipedia.org/wiki/Nassi-Shneiderman-Diagramm

von Jens R. (homerqlb)


Bewertung
0 lesenswert
nicht lesenswert
Na gut, vielen Dank für die gut gemeinten Ratschläge.
Aber ich baue das Ganze jetzt konventionell, Schritt für Schritt auf. So 
komplex ist das Konstrukt nun wieder auch nicht.
Ich will am Anfang nicht gleich eine Rakete bauen, fange besser erstmal 
mit einem Papierflugzeug an. Es bringt nichts, wenn ich mich mit Dingen 
beschäftige, wo das Reindenken länger dauert, als einen ersten 
funktionierenden Code zu schreiben. Später kann man immer noch, wenn 
überhaupt nötig, optimieren, oder zusätzliche Funktionen einbauen.
Wie schon gesagt, mein eigentliches Projekt ist die Säge und nicht die 
Programmierung eines µC für dessen Steuerung.

von Jens R. (homerqlb)


Bewertung
-2 lesenswert
nicht lesenswert
So hier mal der ungetestete Code für das Anfahren des Schrittmotors Bis 
zum Endschalter.
Die delay`s sind gewollt, da ist auch die Maschine inaktiv.
An allen ausführenden Punkten habe ich eine Start/Stop-Tasterabfrage 
eingefügt.
Auch wenn keiner goto braucht, habe ich es hier verwendet, um aus dem 
laufenden Programm komplett rauszukommen und einen End-Code auszuführen.
Ein Neustart ist jeder Zeit möglich.
Was meint ihr dazu?
void loop() {
  if (Labelsprung == 1) goto Aus;
  if (digitalRead(StartPin) == LOW) { //wenn Starttaste gedrückt
    delay(1000); //Wartezeit um Doppelschaltung zu verhindern
    digitalWrite(DirPin, HIGH); //Richtung Endschalter
    for (StepTime = StepMin; StepTime >= StepMax; StepTime = StepTime - StepStepup) { //Schleife Hochtouren Schrittmotor
      Time = millis(); //akt. Zeit
      while (millis() <= Time + StepTime) { //Schleife Zeitablauf nächste Step
        if (digitalRead(StartPin) == LOW)goto Aus; //AUS
        if (millis() >= Time + StepTime) { //bei akt. Zeit = errechneter Schaltzeit
          digitalWrite(StepPin, !digitalRead(StepPin)); //StepPin umschalten
        }
      }
    }
    while (digitalRead(EndPin) == HIGH) { //Fahren Richtung Endschalter
      if (digitalRead(StartPin) == LOW)goto Aus; //AUS
      Time = millis(); //akt. Zeit
      while (millis() <= Time + StepTime) { //Schleife Zeitablauf nächster Step
        if (millis() >= Time + StepTime) { //bei akt. Zeit = errechneter Schaltzeit
          digitalWrite(StepPin, !digitalRead(StepPin)); //StepPin umschalten
        }
      }
    }
  }

  goto weiter;
Aus: {
    Labelsprung = 1;
    if (digitalRead(StartPin) == LOW) Labelsprung = 0;
    delay(1000);//Wartezeit um Doppelschaltung zu verhindern
  }
weiter: {}
}

von STK500-Besitzer (Gast)


Bewertung
1 lesenswert
nicht lesenswert
Jens R. schrieb:
> Was meint ihr dazu?

Dir ist nict zu helfen.

Um Schleifen zu verlassen, verwendet man "break;" oder eine (weitere) 
Abbruchbedingung.

von Johannes S. (jojos)


Bewertung
0 lesenswert
nicht lesenswert
und wenn es lieber Spaghetti werden soll bin ich auch raus, mein 
Programmrumpf hat doch schon fast alles gemacht. Weitere Schritte da 
einfügen ist das enum und das switch case um ein weiteres Element 
erweitern.

von Johannes S. (jojos)


Bewertung
0 lesenswert
nicht lesenswert
Jens R. schrieb:
> Ich muß aber jedesmal vorher die switch-Variable entsprechend zuweisen.
> Starttaste hat aber z.B. 2 Funktionen.

nein, der Zustand ist in meinem Muster global und bleibt solange gesetzt 
bis er geändert wird.
Die Starttaste würde ich nicht doppelt belegen, besser eine Stoptaste 
die in jedem Fall Stop macht und damit alle Bewegungen abbricht.
In dem Fall muss für Start auch erst eine definierte Ausgangslage 
geschaffen werden, bei Start einfach losfahren ist auch nicht richtig. 
Hatte ich auch schon geschrieben:

Johannes S. schrieb:
> Für die Schrittkette überlegtst du dir was jeweils passieren soll:
>  0 stateIdle : Ruhezustand, keine Änderungen
>  1 stateMoveHome : Säge ausschalten. wenn nicht in Hompos, Schlitten in
> Homeposition fahren auslösen. wenn in Homepos, state++

Wenn es gut werden soll startet man noch einen Überwachungstimer für die 
Fahrfunktion: Fehler, wenn der Enschalter nicht nach einer max. Zeit 
erreicht wurde.

Das ist mit dem µC nicht aufwändig, bietet dafür mehr Sicherheit als 
eine dumme Relaissteuerung.

von Jens R. (homerqlb)


Bewertung
-2 lesenswert
nicht lesenswert
S

STK500-Besitzer schrieb:
> Um Schleifen zu verlassen, verwendet man "break;" oder eine (weitere)
> Abbruchbedingung.

Ja aber auch nur aus der laufenden Schleife, oder ist das nicht so?. Ich 
möchte aber mit dem Aus-Schalter die Bearbeitung sofort abbrechen. Da 
erschien mir der Sprung zu Aus-label am schnellsten.

STK500-Besitzer schrieb:
> Dir ist nict zu helfen.

Ja leider!

von Jens R. (homerqlb)


Bewertung
0 lesenswert
nicht lesenswert
Johannes S. schrieb:
> Die Starttaste würde ich nicht doppelt belegen, besser eine Stoptaste
> die in jedem Fall Stop macht und damit alle Bewegungen abbricht.

Schade, das Geld für eine 2.Taste wollte ich mir sparen. Ich muß doch 
jetzt schon an die Kosten denken, wenn ich in Großserie gehe;-)
Nun gut, wenigstens das leuchtet mir ein. Ich werde es überdenken, aber 
wenn`s hart auf hart kommt und ich habe 2 Tasten zur Auswahl, 
hoffentlich drücke ich in der Hektik dann die richtige. Ein 
Notausschalter in der Netzleitung ist auf jeden Fall geplant.

Johannes S. schrieb:
> nein, der Zustand ist in meinem Muster global und bleibt solange gesetzt
> bis er geändert wird.

Ich bin ganz ehrlich, dein Programm kann ich leider nicht nachvollziehen 
und das liegt gewiss nicht an dir.

Johannes S. schrieb:
> Wenn es gut werden soll startet man noch einen Überwachungstimer für die
> Fahrfunktion: Fehler, wenn der Enschalter nicht nach einer max. Zeit
> erreicht wurde.

Ja, Stück für Stück. Ich habe gemerkt, dass ich mit einem kompletten 
Programmcode aus der Hüfte nicht weit komme.

von Johannes S. (jojos)


Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
für den Anfang sollte man zumindest die von Arduino mitgelieferten 
Beispiele aus Control durchsehen und verstehen. Das sind die 
Standardkostrukte für Abfragen, Schleifen und Switch drin.

Weil ich das Programm in ähnlicher Form auch gebrauchen kann habe ich 
die Endschalter und den Ablauf auch noch eingebaut.

Als Anfänger neigt man natürlich dazu alles in ein meterlanges main bzw. 
beim Arduino loop() zu Schreiben, aber sowas will keiner lesen. Deshalb 
sofort angewöhnen mit Unterprogrammen zu strukturieren.

Der Code macht die Initialisierung der Ports im setup(), das sollte 
leicht verständlich sein. Arduino blöd finde ich nur die Art wie PullUps 
aktiviert werden, ist aber einfach so.

Im loop() wird dann einfach das Einlesen, Verarbeiten von Wartezeit und 
Zustand ausgeführt. Immer wieder im Kreis rum ohne anzuhalten.

Wenn nix zu tun ist, wird immer in den idle Zustand gesprungen und es 
passiert nichts. Wenn die Starttaste gedrückt wird, dann wird der 
Zustand auf stateStart gesetzt. Von da an passieren die Dinge in der 
Reihenfolge wie sie sollen. Aber eben so, das nicht auf etwas gewartet 
wird, sondern wenn z.B. eine Position nicht erreicht ist dann wird das 
processStateMachine wieder verlassen und beim nächsten mal wieder 
geprüft.

Das kann man mit den Tasten und Endschaltern testen, im Serial Monitor 
gibt s Ausgaben.

von Jens R. (homerqlb)


Bewertung
-2 lesenswert
nicht lesenswert
Johannes S. schrieb:
> Als Anfänger neigt man natürlich dazu alles in ein meterlanges main bzw.
> beim Arduino loop() zu Schreiben, aber sowas will keiner lesen.

Ja das habe ich gemacht und es funktioniert schon mal zufriedenstellen.

Johannes S. schrieb:
> Deshalb sofort angewöhnen mit Unterprogrammen zu strukturieren.

Das ist es, was ich auf der Arbeit in Label, dort nach dem 
Hauptprogramm, schreibe und diese aus dem Hauptprogramm bei Bedarf 
aufrufe. Toll, dass das
hier auch funktioniert.

Johannes S. schrieb:
> für den Anfang sollte man zumindest die von Arduino mitgelieferten
> Beispiele aus Control durchsehen und verstehen. Das sind die
> Standardkostrukte für Abfragen, Schleifen und Switch drin.

Wird gemacht!

Johannes S. schrieb:
> Im loop() wird dann einfach das Einlesen, Verarbeiten von Wartezeit und
> Zustand ausgeführt. Immer wieder im Kreis rum ohne anzuhalten.

So habe ich mir das auch gedacht.

Johannes S. schrieb:
> im Serial Monitor
> gibt s Ausgaben.

Da habe ich leider noch nicht verstanden, wie ich das nutzen kann.


Dein Code ist ziemlich umfangreich, aber ich glaube die Struktur zu 
erkennen.
Sehr schön!
und Danke

von Jens R. (homerqlb)


Bewertung
-2 lesenswert
nicht lesenswert
Johannes S. schrieb:
> Deshalb
> sofort angewöhnen mit Unterprogrammen zu strukturieren.

Eben das versuch ich gerade.
Ich habe jetzt für alle Funktionen ein eigenes void geschrieben.
Also:
SM-Motor hochtouren
SM-Motor fahren
SM-Motor abtouren
BL-Motor hochtouren
BL-Motor fahren
BL-Motor abtouren
Über if-Abfragen der Endschalter kann ich jetzt jeden nötigen Schritt 
ausführen.
Jetzt möchte ich über Interrupts den Starttaster als Ausschalter 
benutzen, den ESC über Interrupt alle -zig ms aktualisieren.
Bevor ich damit anfange, ist bis hierher alles richtig?

von Johannes S. (jojos)


Bewertung
0 lesenswert
nicht lesenswert
Jens R. schrieb:
> Ich habe jetzt für alle Funktionen ein eigenes void geschrieben.

void ist der Rückgabetyp, man schreibt kein void. Aber ich verstehe 
schon was du meinst, du hast Unterprogramme geschrieben.

Jens R. schrieb:
> Jetzt möchte ich über Interrupts den Starttaster als Ausschalter
> benutzen, den ESC über Interrupt alle -zig ms aktualisieren.
> Bevor ich damit anfange, ist bis hierher alles richtig?

Kann man über Ints machen, nur die Doppelbelegung Start/Stop würde ich 
nicht so machen. Das muss jedenfalls gut entprellt werden und EMV fest 
sein, nicht das die Säge losrennt wenn du Licht oder ein Gerät daneben 
einschaltetst.

Die Servo Lib vom Arduino ist gar nicht schlecht, die arbeitet schon mit 
Interrupt und der Wert muss nicht in jedem Zyklus neu gesetzt werden.
Und mit AccelStep gibt es eine gut Lib für SM, die läuft ebenfalls über 
HW Timer. Man muss nur aufpassen das sich die HW Resourcen nicht in die 
Quere kommen.

von Jens R. (homerqlb)


Bewertung
-2 lesenswert
nicht lesenswert
Johannes S. schrieb:
> Kann man über Ints machen, nur die Doppelbelegung Start/Stop würde ich
> nicht so machen. Das muss jedenfalls gut entprellt werden und EMV fest
> sein, nicht das die Säge losrennt wenn du Licht oder ein Gerät daneben
> einschaltetst.

Also genügt die delay-Zeit nach der Starttasterbetätigung wohl nicht zum 
Entprellen. Aber kann dieser ominöse EMV nicht jederzeit vorkommen?
Nun ich werde wohl einen separaten Aus-Schalter einzufügen.
Not-Aus zur Netzttrennung muß aber trotzdem sein!
Dann habe ich schon 3 Schalter. 1-2oder 3 letzte Chance...

Johannes S. schrieb:
> Die Servo Lib vom Arduino ist gar nicht schlecht, die arbeitet schon mit
> Interrupt und der Wert muss nicht in jedem Zyklus neu gesetzt werden.
> Und mit AccelStep gibt es eine gut Lib für SM, die läuft ebenfalls über
> HW Timer.

Wenn das so einfach ist, bediene ich mich dann mal ganz frech.

Johannes S. schrieb:
> Man muss nur aufpassen das sich die HW Resourcen nicht in die
> Quere kommen.

Du meinst, die beiden Pin`s, die ich für interrupt zur Verfügung habe?

von Johannes S. (jojos)


Bewertung
1 lesenswert
nicht lesenswert
Jens R. schrieb:
> Aber kann dieser ominöse EMV nicht jederzeit vorkommen?

ja, nur Interrupts reagieren da schnell empfindlich. Keine lange Leitung 
dranmachen, und ext. RC Glied würde ich einsetzen. Bzw. sowieso lieber 
meine Polling Lösung. Über Polling vs. Ints gibts hier ja gerade mehrere 
Diskussionen...

Jens R. schrieb:
> Du meinst, die beiden Pin`s, die ich für interrupt zur Verfügung habe?

nein, die HW Timer Resourcen. Wenn man nicht weiss wie die Libs intern 
arbeiten und die belegten Resourcen nicht dokumentiert sind kann die 
Kombination mehrerer Libs schief gehen. Versuch macht kluch, oder eben 
in die Internas gucken.

von Wolfgang (Gast)


Bewertung
1 lesenswert
nicht lesenswert
Jens R. schrieb:
> Aber kann dieser ominöse EMV nicht jederzeit vorkommen?

EMV ist eine gute Sache. Eigentlich wünscht man sich die als 
Dauerzustand.
https://de.wikipedia.org/wiki/Elektromagnetische_Vertr%C3%A4glichkeit

von sid (Gast)


Bewertung
-1 lesenswert
nicht lesenswert
Jens R. schrieb:
> Deswegen hätte ich >=/<= im Vergleich genommen, um den richtigen Moment
> nicht zu verpassen,

das ist aber auch noch "unzureichend" eventuell..
die laufen nämlich irgendwann über

in einigen Arduino IDEs gibt's n kleineren Schluckauf,
und der rollover passiert nach etwa neuneinhalb stunden
(was bei "langer" Laufzeit ein Problem sein könnte)
bei Neueren Versionen wurd das meine ich gefixxt und der Rollover ist 
tatsächlich erst nach 49 Tagen zu erwarten;
was vermutlich eh nie eintrifft, weil man alle paar tage das Dingen mal 
zur "wartung" abschaltet.

korrekt verhindern kann man den Fehler aber in etwa so:
// ins init:
const unsigned long STEP = 5*1000UL; //ich nahm einfach mal 5 sek...
static unsigned long lasttime; // brauchen wir zum Vergleich

// dann irgendwann:
if ( millis() - lasttime >= STEP )
{ //hier was auslösen und
    lasttime += STEP; // das läuft zeitgleich über und der vergleich stimmt wieder
}

wie gesagt in etwa so ...
also sofern das Dingen wirklich im permanenten Dauerbetrieb ist,
wenn es nur n stündchen oder zwei am Stück läuft bist Du so weit vom 
Überlauf weg, dass es keinen Unterschied macht :D

'sid

von Jens R. (homerqlb)


Bewertung
-2 lesenswert
nicht lesenswert
Johannes S. schrieb:
> ja, nur Interrupts reagieren da schnell empfindlich. Keine lange Leitung
> dranmachen, und ext. RC Glied würde ich einsetzen. Bzw. sowieso lieber
> meine Polling Lösung. Über Polling vs. Ints gibts hier ja gerade mehrere
> Diskussionen...

Also Hardwareentprellung!

Johannes S. schrieb:
> nein, die HW Timer Resourcen. Wenn man nicht weiss wie die Libs intern
> arbeiten und die belegten Resourcen nicht dokumentiert sind kann die
> Kombination mehrerer Libs schief gehen. Versuch macht kluch, oder eben
> in die Internas gucken.

Ich habe gelesen, dass 2 interrupts auf meinem Arduniono Nano laufen 
müßten.
So würde ich den einen für den ESC und den anderen für den Stop 
verwenden.
Damit könnte ich das von `sid` angesprochene Überlaufproblem auch 
loswerden, indem ich wieder mit delay rummurkse und es mir einfach 
mache.
Da der interrupt auch hinter dem Delay läuft wäre eine Entprellung mit 
delay und Verwendung eines Tasters für Start/Aus sowieso sinnlos, also 
kommt nun endgültig ein 2. Schalter rein.

von sid (Gast)


Bewertung
0 lesenswert
nicht lesenswert
zwei endschalter machen immer Sinn mMn;
im Grunde kann alles passieren und man will sich selbst das Leben ja 
nicht schwerer machen als nötig.

Beispiel: optischer endschalter wird versehentlich zu früh ausgelöst
(Späne, Kabel, unvorsichtiger Humanoid, ne Fliege krabbelt drüber...)
der Automat hält seine Null Referenz nun fälschlich als 10cm vor dem 
eigentlichen Nullpunkt an..
ohne zweiten Endschalter versucht er nun 10 über das hintere Ende 
hinauszufahren (und das wird schnell gruselig)

Also n zweiter Endschalter (entweder getrennt oder aber in Reihe)
kann Mechanik retten wenn man mal nicht aufpasst.

Ausserdem muss man keine Schritte zählen oder verlorene Schritte 
befürchten.
(schritte zählen macht aber zur Fehlersuche sinn.. 4000 schritte hin und 
4200 zurück bedeutet man hat ein Problem um das man sich ggf kümmern 
sollte ;))

Endschalter würde ich wie Notausschalter an einen interrupt klemmen 
ehrlich gesagt.. beim polling kann man sich leichter 'verrechnen' mit 
schleifenlaufzeiten und so... das kann ggf auch Probleme machen.
aber wir wollen diese Diskussion vielleicht nicht überall hintragen ;)

falls Du eine ISR benutzt,
dann denk unbedingt daran sie so kurz wie irgendmöglich zu halten
und niemals nie ein delay oder auch nur eine zweite millis-abfrage drin 
zu haben, innerhalb der isr steht die zeit nämlich still!

'sid

von Jens R. (homerqlb)


Bewertung
-2 lesenswert
nicht lesenswert
Ich möchte nach Schalten des Aus-Taster per interrupt ein Unterprogramm 
ausführen lassen. Nach dessen Abarbeitung springt das Programm an die 
Stelle der Unterbrechung zurück. Nun soll dort die loop-Schleife zum 
Start springen . Wie bewerkstelle ich so etwas?

von Jens R. (homerqlb)


Bewertung
-1 lesenswert
nicht lesenswert
Ich hatte mal wieder etwas Zeit und einen Code geschrieben. Es scheint 
ja wenigstens noch einen zu geben, der meine Beiträge liest(siehe 
Bewertungen), denn man kann ja erst bewerten, wenn man gelesen hat.
Hier meine neueste Murksversion:
#include "ESC.h"
#define SPEED_MIN 1000                        // Set the Minimum Speed in microseconds
#define SPEED_MAX 2000                        // Set the Minimum Speed in microseconds
#define DirPin  8                             //Dir Schrittmotor
#define StepPin 7                             //Step Schrittmotor
#define EndPin  6                             //Endschalter
#define AnfPin  5                             //Anfangsschalter
#define ESCPin  4                             //Motordrehzahl
#define StartPin  3                           //Starttaster
#define StopPin  2                            //Stoptaster
ESC BL (ESCPin, SPEED_MIN, SPEED_MAX, 1000);  //ESC_Name (ESC PIN, Minimum Value, Maximum Value, Default Speed, Arm Value)
int ESC;                                      //Variable for the speed sent to the ESC
int StepMin = 2000;                           //HIGH/LOW-Zeit min. Geschwindigkeit Schrittmotor
int StepMax = 600;                            //HIGH/LOW-Zeit max. Geschwindigkeit Schrittmotor
int StepStepup = 100;                         //Steigerung Rampe Schrittmotor Hochtouren
int StepStepdown = 1000;                      //Steigerung Rampe Schrittmotor Abtouren
volatile int StepTime ;                       //HIGH/delay Schrittmotor
int PinAbfr;                                  //abzufragender End/Anfangsschalter
volatile int StopStatus = 0;                  //Status Stoptaster

void setup() {
  pinMode (ESCPin, OUTPUT);                   //PIN ESC Motorspeed
  pinMode (DirPin, OUTPUT);                   //PIN Dir Schrittmotor
  pinMode (StepPin, OUTPUT);                  //PIN Step Schrittmotor
  pinMode (EndPin, INPUT_PULLUP);             //PIN Endschalter
  pinMode (AnfPin, INPUT_PULLUP);             //PIN Anfangsschalter
  pinMode (StopPin, INPUT_PULLUP);            //PIN Stoptaster
  attachInterrupt(0, AUS, LOW);               //PIN 2 StopPin interrupt aktiviert
}

void SM_Fahr() {                                      // Schrittmotor fahren bis End/Anfangsschalter, Unterbrechung bei Stoptaster
  StepTime = StepMin;
  StepTime = StepTime + StepStepup;
  while (StepTime <= StepMax) {                       //Schrittmotor beschleunigen
    if (StopStatus == 1)break;
    if (PinAbfr == HIGH) {
      digitalWrite(StepPin, !digitalRead(StepPin));   //StepPin umschalten
      delay(StepTime);
      StepTime = StepTime + StepStepup;
    }
  }
  if (PinAbfr == HIGH) {                              //Schrittmotor bis Schalter fahren
    digitalWrite(StepPin, !digitalRead(StepPin));     //StepPin umschalten
    delay(StepTime);
  }
  StepTime = StepMax;
  StepTime = StepTime - StepStepdown;
  while (StepTime >= StepMin) {                       //Schrittmotor abbremsen
    if (StopStatus == 1)break;
    digitalWrite(StepPin, !digitalRead(StepPin));     //StepPin umschalten
    delay(StepTime);
    StepTime = StepTime - StepStepdown;
  }
}

void BL_up() {//BL-Motor hochtouren
  for (ESC = SPEED_MIN; ESC <= SPEED_MAX; ESC += 1) { // goes from 1000 microseconds to 2000 microseconds
    if (StopStatus == 1)break;
    BL.speed(ESC);                                    // tell ESC to go to the oESC speed value
    delay(10);                                        // waits 10ms for the ESC to reach speed
  }
}

void BL_down() {//BL-Motor abtouren
  for (ESC = SPEED_MAX; ESC >= SPEED_MIN; ESC -= 1) { // goes from 2000 microseconds to 1000 microseconds
    if (StopStatus == 1)break;
    BL.speed(ESC);                                    // tell ESC to go to the oESC speed value
    delay(10);                                        // waits 10ms for the ESC to reach speed
  }
}

void AUS() {                                          //Unterbrechnung bei Stoptaster gedrückt (interrupt)
  BL.speed(SPEED_MIN);
  StopStatus = 1;
}

void ANFANG() {                                       //Fahr zur Anfangspos.(am Endschalter BL aus)

  PinAbfr = AnfPin;
  digitalWrite(DirPin, LOW);
  SM_Fahr();
  if (EndPin == LOW)BL_down();
}

void ENDE() {                                         //Fahr zur Endpos. (BL an)
  PinAbfr = EndPin;
  BL_up();
  digitalWrite(DirPin, HIGH);
  SM_Fahr();
}

void loop() {
  if (digitalRead(StartPin) == LOW) {//wenn Starttaste gedrueckt geht`s los
    if ((digitalRead(AnfPin) == HIGH) && (digitalRead(EndPin) == HIGH)) ANFANG();//wenn Anfangspos. nicht erreicht
    ENDE();
    ANFANG();
    StopStatus = 0;
  }
}
Ich ducke mich schon mal und hoffe auf reichlich Kritik.

von sid (Gast)


Bewertung
-1 lesenswert
nicht lesenswert
Pin 2 ist der Notaus taster?

dann ist es in der tat so einfach:
// in der setup()...
pinMode(StopPin, INPUT_PULLUP); 
attachInterrupt(digitalPinToInterrupt(StopPin), AUS, LOW); //ich würde FALLING bevorzugen aber das ist gusto
digitalPinToInterrupt stellt sicher, dass der passende Interrupt zum Pin 
gewählt ist, Du kannst manuell konfigurieren, aber das kann bei 
boardwechsel in die Hose gehen... deswegen so in der "sichereren" 
Version.

Ich bin kein fan der main loop um ehrlich zu sein..
ende anfang anfang ende anfang stop... uiuiui
ich bin schon kein fan von uppercase funktionsnamen, aber auch hier das 
ist nur Geschmacksache,
Camelcase liest sich mir leichter
upper defines const und co,
lowercase variablen (und ggf unterstrich)
camelcase funktionen
Aber egal; geht ja hier nciht um n Schönheitspreis oder was MIR besser 
gefällt ;)

Ich seh jetzt akut keinen logischen Fehler, wenngleich mir der 
SpeedController nicht ausreichend definiert ist um eine Aussage dazu zu 
treffen, geh ich davon aus Du hast die includes dazu und weisst sie zu 
lesen und verstehen (ergo auch zu benutzen).

Das einzige was mir n bisserl sauer aufstösst
is die SM_FAHR
das ist ziemlicher kokolores...
(obschon das dennoch fast laufen sollte)
void SM_Fahr()
{ 
  /* was soll denn das hier zB */
  StepTime = StepMin;
  StepTime = StepTime + StepStepup;
  
  /* diese einzelne Zeile täte dasselbe */
  StepTime = StepMin + StepStepup; 
  
  /* while dann schritt dann if dann while kommt mir oll vor */
  while (StepTime <= StepMax) {                       //Schrittmotor beschleunigen
    if (StopStatus == 1)break;
    if (PinAbfr == HIGH) {
      StepTime = StepTime + StepStepup;
    }
  }
  /* wieso IF?? muss das doch while sein, oder ?  IF machte Dir nur einen einzelschritt!*/
  if (PinAbfr == HIGH) {                              //Schrittmotor bis Schalter fahren
    digitalWrite(StepPin, !digitalRead(StepPin));     //StepPin umschalten
    delay(StepTime);
  }
  /* und wieder */
  StepTime = StepMax;
  StepTime = StepTime - StepStepdown;
  
  /*  wo diese einzelne Zeile dasselbe  täte*/
  StepTime = StepMax - StepStepdown;
  
  /*abbremsen ist ja schön, aaaber eben nur möglich falls Du nicht schon den endschalter berührt hast, dann sollte er sofort stehen */
  while (StepTime >= StepMin) {                       //Schrittmotor abbremsen
    if (StopStatus == 1)break;
    digitalWrite(StepPin, !digitalRead(StepPin));     //StepPin umschalten
    delay(StepTime);
    StepTime = StepTime - StepStepdown;
  }
}

/*würde ich also eher wie folgt: */
void SM_Fahr()
{ 
  StepTime = StepMin; // langsamste Geschwindigkeit (ww mit erster erhöhung?)
  
  while (PinAbfr == HIGH) { // schalter noch nicht erreicht
    if (StopStatus == 1)break; // immer anhalten wenn Notaus gedrückt!!
    // fahren:
    digitalWrite(StepPin, !digitalRead(StepPin));   //StepPin umschalten
    delay(StepTime);
    if (StepTime <= StepMax) StepTime += StepStepup; //Schrittmotor beschleunigen falls noch nicht schnell genug
  }
  
  // schalter erreicht abbremsen (mMn leider unmöglich so)
  /*
  while (StepTime >= StepMin) {                       //Schrittmotor abbremsen
    if (StopStatus == 1)break;
    digitalWrite(StepPin, !digitalRead(StepPin));     //StepPin umschalten
    delay(StepTime);
    StepTime = StepTime - StepStepdown;
  }
  */
}

beim rest halte ich die Funktionen für teils unnötig, teils unsinnig;
aber soweit ich sehen kann jdf nicht falsch und darum geht's ja 
letztendlich, richtig?

'sid

von sid (Gast)


Bewertung
0 lesenswert
nicht lesenswert
watt? warte.. is schon spät.. das ist doch käse.. speed max kleiner 
speed min und dann delays und was?

Ich muss mal ne runde nickern und komm drauf zurück, aber das ist doch 
schlimmer als zunächst angenommen fürhte ich

'sid

von sid (Gast)


Bewertung
-1 lesenswert
nicht lesenswert
Manman.. ESC war auch mächtig im Weg ;)

hab ich mal alles wegrationalisiert was ging.
#include "ESC.h"
#define SPEED_MIN 1000                        // Set the Minimum Speed in microseconds
#define SPEED_MAX 2000                        // Set the Minimum Speed in microseconds
#define DirPin  8                             // Dir Schrittmotor
#define StepPin 7                             // Step Schrittmotor
#define EndPin  6                             // Endschalter
#define AnfPin  5                             // Anfangsschalter
#define ESCPin  4                             // Motordrehzahl
#define StartPin  3                           // Starttaster
#define StopPin  2                            // Stoptaster
ESC BL (ESCPin, SPEED_MIN, SPEED_MAX, 1000);  // ESC_Name (ESC PIN, Minimum Value, Maximum Value, Default Speed, Arm Value)
int StepdelayMin = 600;                       // HIGH/LOW-Zeit min. Geschwindigkeit Schrittmotor
int StepdelayMax = 2000;                      // HIGH/LOW-Zeit max. Geschwindigkeit Schrittmotor
int StepSpeedup = 100;                        // Steigerung Rampe Schrittmotor Hochtouren
volatile int StepTime ;                       // HIGH/delay Schrittmotor
volatile int StopStatus = 0;                  // Status Stoptaster

//ISR
void NotAus() 
{                                             //Unterbrechnung bei Stoptaster gedrückt (interrupt)
  BL.speed(SPEED_MIN);
  StopStatus = 1;
}

void setup()
{
  pinMode (ESCPin, OUTPUT);                   // PIN ESC Motorspeed
  pinMode (DirPin, OUTPUT);                   // PIN Dir Schrittmotor
  pinMode (StepPin, OUTPUT);                  // PIN Step Schrittmotor
  pinMode (EndPin, INPUT_PULLUP);             // PIN Endschalter
  pinMode (AnfPin, INPUT_PULLUP);             // PIN Anfangsschalter
  pinMode (StopPin, INPUT_PULLUP);            // PIN Stoptaster
  attachInterrupt(digitalPinToInterrupt(StopPin), NotAus, FALLING); // PIN 2 StopPin interrupt aktiviert
}

void SM_Fahr(&Pin)
{ 
  StepTime = StepdelayMax; // langsamste Geschwindigkeit (ww mit erster erhöhung?)
  
  while (digitalRead(Pin) == HIGH) // schalter noch nicht erreicht
  { 
    if (StopStatus == 1)
      break; // immer anhalten wenn Notaus gedrückt!!
    // fahren:
    digitalWrite(StepPin, !digitalRead(StepPin));   //StepPin umschalten
    delay(StepTime);
    if (StepTime >= StepdelayMin) StepTime -= StepSpeedup; //Schrittmotor beschleunigen falls noch nicht schnell genug
  }
  
}

void BL_speed(bool increase) 
{
  int spd_diff = SPEED_MAX - SPEED_MIN;
  for (int i = 0; i <= spd_diff; i++)
  { 
    if (StopStatus == 1)
      break;
    if (increase) 
      BL.speed(SPEED_MIN+i); // increase
    else 
      BL.speed(SPEED_MAX-i); // decrease
  }
}

void ANFANG()                                        //Fahr zur Anfangspos.(am Endschalter BL aus)
{
  digitalWrite(DirPin, LOW);
  SM_Fahr(AnfPin);
  if (digitalRead(EndPin) == LOW)
    BL_speed(false); //decrease speed
}

void ENDE()                                           //Fahr zur Endpos. (BL an)
{
  digitalWrite(DirPin, HIGH);
  BL_speed(true); //increase speed
  SM_Fahr(EndPin);
}

void loop() 
{
  if (digitalRead(StartPin) == LOW) //wenn Starttaste gedrueckt geht`s los
  {
    StopStatus = 0; //zurücksetzen sonst geht nix ggf
    if ((digitalRead(AnfPin) == HIGH) && (digitalRead(EndPin) == HIGH)) 
      ANFANG();//wenn Anfangspos. nicht erreicht
                // was wenn die säge nicht läuft kann man dann gefahrlos zurückfahren?
    ENDE();
    ANFANG();
  }
}

ist mir so immernoch nicht recht, aber wie gesagt ist spät und der Kopp 
ist bisserl Brei ....
ich guck wacher nochmal drüber
(vllt find ich ja auch die esc.h auf meinem anderen Puter :D)

'sid

von Jens R. (homerqlb)


Bewertung
-2 lesenswert
nicht lesenswert
sid schrieb:
> int StepdelayMin = 600;                       // HIGH/LOW-Zeit min.
> Geschwindigkeit Schrittmotor
> int StepdelayMax = 2000;                      // HIGH/LOW-Zeit max.
> Geschwindigkeit Schrittmotor

ist ein bisschen verwirrend, aber kürzere Zeit =höhere Geschwindigkeit, 
oder?
Ich glaube deiner Bezeichnung `delay` ist das eindeutiger.

sid schrieb:
> void SM_Fahr(&Pin)
> {
>   StepTime = StepdelayMax; // langsamste Geschwindigkeit (ww mit erster
> erhöhung?)
>
>   while (digitalRead(Pin) == HIGH) // schalter noch nicht erreicht
>   {
>     if (StopStatus == 1)
>       break; // immer anhalten wenn Notaus gedrückt!!
>     // fahren:
>     digitalWrite(StepPin, !digitalRead(StepPin));   //StepPin umschalten
>     delay(StepTime);
>     if (StepTime >= StepdelayMin) StepTime -= StepSpeedup;
> //Schrittmotor beschleunigen falls noch nicht schnell genug
>   }

Sieht besser aus als bei mir.

sid schrieb:
> void SM_Fahr(&Pin)

Wofür steht hier (&Pin)?

sid schrieb:
> void BL_speed(bool increase)
> {
>   int spd_diff = SPEED_MAX - SPEED_MIN;
>   for (int i = 0; i <= spd_diff; i++)
>   {
>     if (StopStatus == 1)
>       break;
>     if (increase)
>       BL.speed(SPEED_MIN+i); // increase
>     else
>       BL.speed(SPEED_MAX-i); // decrease
>   }
> }

Da kann ich nicht ganz folgen, wofür steht BL.speed?

sid schrieb:
> ANFANG();//wenn Anfangspos. nicht erreicht
>                 // was wenn die säge nicht läuft kann man dann gefahrlos
> zurückfahren?

Am Start soll die Säge in Ausgangspos. fahren, ohne laufenden Motor um 
keinen zu verletzen. Das wäre nach einem Abbruch. Dass das ohne 
laufenden Sägenmotor geht, muß ich vor Drücken der Starttaste absichern. 
Allerdings, wahrscheinlich habe ich den Abbruch herbeigeführt, da etwas 
nicht stimmt. So sollte vielleicht nach Anfahren der Startpos. durch 
nochmaliges Start drücken der Arbeitsvorgang erst dann in Gang gesetzt 
werden. Da muß ich mir nochmal Gedanken drüber machen.
Überhaupt verwirren mich die vielen Funktionen mehr, als dass sie mir 
Struktur geben. Ist es vielleicht doch besser, die paar Funktionen 
gleich ins loop zu schreiben?
Auf jeden Fall kann ich deiner Korrektur schon mal halbwegs folgen.
Danke dafür.
Die ESC.h habe ich im Arduino 1.8.12
-Bibliotheken verwalten
-Suche `brushless`
-`Brushless Servo`
gefunden. Sie setzt wohl auf die servo.h auf

von sid (Gast)


Bewertung
-1 lesenswert
nicht lesenswert
Deine Benennungen sind echt verwirrend für mich,
ich hab mal so zusammengekürzt wie ich meine dass es am meisten Sinn 
macht;
hab auch ein paar variablen entfernt (weil nutzlos) oder umbenannt(weil 
zu verwirrend)
Ich denke Du solltest das einigermassen nachvollziehen können
wenn Du Zeile für zeile vergleichst
ich hab eine ESC.h die passt gefunden, schau mal ob's dieselbe ist, 
falls nicht, bitte anhängen (geht drum ob's ein arm() und ein stop() 
command gibt)
/*
Assuming
https://github.com/RB-ENantel/RC_ESC
https://www.robotshop.com/community/blog/show/rc-speed-controller-esc-arduino-library
*/
#include "ESC.h"
#define SPEED_MIN 1000                        // Set the Minimum Speed in microseconds
#define SPEED_MAX 2000                        // Set the Minimum Speed in microseconds
#define DirPin  8                             // Dir Schrittmotor
#define StepPin 7                             // Step Schrittmotor
#define EndPin  6                             // Endschalter
#define AnfPin  5                             // Anfangsschalter
#define ESCPin  4                             // Motordrehzahl
#define StartPin  3                           // Starttaster
#define StopPin  2                            // Stoptaster
ESC BL (ESCPin, SPEED_MIN, SPEED_MAX, 500);   // ESC_Name (ESC PIN, Minimum Value, Maximum Value, Default Speed, Arm Value)
int StepdelayMin = 500;                       // HIGH/LOW-Zeit min. Geschwindigkeit Schrittmotor
int StepdelayMax = 2000;                      // HIGH/LOW-Zeit max. Geschwindigkeit Schrittmotor
int StepSpeedup = 100;                        // Steigerung Rampe Schrittmotor Hochtouren
volatile bool StopFlag = false;               // Flag gesetzt durchStoptaster

//ISR
void NotAus()                                 // Unterbrechnung bei Stoptaster gedrückt (interrupt)
{
  BL.stop();                                // Motor stoppen macht mehr sinn als langsam weiterlaufen zu lassen IMHO
  StopFlag = true;                          // Stop Flag setzen
}

void setup()
{
  pinMode (ESCPin, OUTPUT);                                         // PIN ESC Motorspeed
  pinMode (DirPin, OUTPUT);                                         // PIN Dir Schrittmotor
  pinMode (StepPin, OUTPUT);                                        // PIN Step Schrittmotor
  pinMode (EndPin, INPUT_PULLUP);                                   // PIN Endschalter
  pinMode (AnfPin, INPUT_PULLUP);                                   // PIN Anfangsschalter
  pinMode (StopPin, INPUT_PULLUP);                                  // PIN Stoptaster
  attachInterrupt(digitalPinToInterrupt(StopPin), NotAus, FALLING); // PIN 2 StopPin interrupt aktiviert
}

void SM_Fahr(int &Pin)                                  // no delay version; Pin ist der zu überwachende Endschalter
{ 
  int StepInc = StepdelayMax;                         // langsamste Geschwindigkeit (ww mit erster erhöhung?)
  unsigned long StepTime = millis() + StepDelayMax;   // Zeitpunkt für ersten Schritt festlegen
  while (digitalRead(Pin) == HIGH)                    // Endschalter noch nicht erreicht
  { 
    while(millis() < StepTime)                      // warten auf den Zeitpunkt 2 sekunden find ich aber arg viel!!
    {
      if (StopFlag)                               // auch beim Warten auf NotAus hören!
        break 2;                                // falls: BEIDE Schleifen unterbrechen
    }
    digitalWrite(StepPin, !digitalRead(StepPin));   // einen Schritt tun
    if (StepInc > StepdelayMin) 
      StepInc -= StepSpeedup;                     // Schrittmotor beschleunigen falls nötig
    StepTime += StepInc;                            // Zeitpunkt für nächsten Schritt festlegen
  }
}

void BL_speed(bool increase)                            // das geht mit einer Funktion und einem Parameter
{
  unsigned int spd_diff = SPEED_MAX - SPEED_MIN;      // der Unterscheid zwischen min und max ist interessant
  for (unsigned int i = 0; i <= spd_diff; i+=10)        // dahin wird gezählt ich hab die Schritte mal erweitert
  { 
    if (StopFlag)                                   // Raus hier bei NotAus
      break;
    if (increase)                                   // welche Richtung
      BL.speed(SPEED_MIN+i);                      // increase (min +  diff)
    else 
      BL.speed(SPEED_MAX-i);                      // decrease (max - diff)
    delay(10);                                      // den delay würd ich mir sparen fast.. aber nundenn
  }
}

void loop() 
{
  if (digitalRead(StartPin) == LOW)                                      // wenn Starttaste gedrueckt geht`s los
  {
    StopFlag = false;                                                  // StopFlag löschen sonst könnte es klemmen
    BL.arm();                                                          // ESC 'bewaffnen'
    BL_speed(true);                                                    // und Säge anwerfen
    if ((digitalRead(AnfPin) == HIGH) && (digitalRead(EndPin) == HIGH))// wenn Anfangspos. nicht erreicht zurück auf Start
    {
      digitalWrite(DirPin, LOW);                                     // DirPin 'rückwärts' setzen
      SM_Fahr(AnfPin);                                               // Fahren zum Endschalter der Anfangsposition
    }
    // zum Ende
    digitalWrite(DirPin, HIGH);                                        // DirPin 'vorwärts' setzen
    SM_Fahr(EndPin);                                                   // Fahren zum Endschalter der Endposition                                                           // einmal vorwärts
    // wieder auf Anfang
    digitalWrite(DirPin, LOW);                                         // DirPin 'rückwärts' setzen
    SM_Fahr(AnfPin);                                                   // Fahren zum Endschalter der Anfangsposition
    
    BL_speed(false);                                                   // Säge langsam anhalten
    BL.stop();                                                         // und wieder abschalten
  }
}

Was passiert erklärt sich in den inline Kommentaren ;)

Jens R. schrieb:
> Wofür steht hier (&Pin)?

&Pin ist der zu überwachende Pin des Endschalters für die 
"Fahranweisung"
(da hab ich nur den typ vergessen)

Jens R. schrieb:
> Da kann ich nicht ganz folgen, wofür steht BL.speed?
BL ist Dein speedcontroller.. BL.speed [BL(PUNKT)speed] setzt die 
Geschwindigkeit des angeschlossenen Motors
BL_speed indes [BL(unterstrich)speed] ist mein Ersatz für Deine beiden 
funktionen die das incrementell tun (BL_up und BL_down .. nur eben in 
einer Funktion uzusammengefasst)

die boolean gibt an in welche Richtung das geschehen soll 
(schneller/langsamer)

Jens R. schrieb:
> Am Start soll die Säge in Ausgangspos. fahren, ohne laufenden Motor um
> keinen zu verletzen. Das wäre nach einem Abbruch.

Wenn die Säge tatsächlich nicht laufen soll wenn das Dingen in die 
Startposition fährt,
dann musst Du den Motor natürlich später anschalten in der loop
also
so
void loop() 
{
  if (digitalRead(StartPin) == LOW)                                      // wenn Starttaste gedrueckt geht`s los
  {
    StopFlag = false;                                                  // StopFlag löschen sonst könnte es klemmen
    if ((digitalRead(AnfPin) == HIGH) && (digitalRead(EndPin) == HIGH))// wenn Anfangspos. nicht erreicht zurück auf Start
    {
      digitalWrite(DirPin, LOW);                                     // DirPin 'rückwärts' setzen
      SM_Fahr(AnfPin);                                               // Fahren zum Endschalter der Anfangsposition
    }
    //Säge anschalten
    BL.arm();                                                          // ESC 'bewaffnen'
    BL_speed(true);                                                    // und Säge anwerfen
    // zum Ende
    digitalWrite(DirPin, HIGH);                                        // DirPin 'vorwärts' setzen
    SM_Fahr(EndPin);                                                   // Fahren zum Endschalter der Endposition                                                           // einmal vorwärts
    // wieder auf Anfang
    digitalWrite(DirPin, LOW);                                         // DirPin 'rückwärts' setzen
    SM_Fahr(AnfPin);                                                   // Fahren zum Endschalter der Anfangsposition
    
    BL_speed(false);                                                   // Säge langsam anhalten
    BL.stop();                                                         // und wieder abschalten
  }
}

hast Du keine arm() und stop() commands für dein benutztes ESC library;
dann musst Du das natürlich wieder entfernen, aber n motor sollte man 
immer auch anhalten können ;)

'sid

von sid (Gast)


Bewertung
-1 lesenswert
nicht lesenswert
UUUPS, Vergebung, man sollte Tipp und Flüchtigkeitsfehler auch entfernen 
bevor man was anbappt.

Dafür hab ich Dir mal ne weiteres define verpasst welches klärt ob Du 
mit oder ohne laufender Säge in die Startposition fährst ;)
wird ja alles wegoptimiert

so jetzt kompiliert die Arduino IDE das auch
/*
  Assuming
  https://github.com/RB-ENantel/RC_ESC
  https://www.robotshop.com/community/blog/show/rc-speed-controller-esc-arduino-library
*/
#include "ESC.h"
#define SPEED_MIN 1000                        // Set the Minimum Speed in microseconds
#define SPEED_MAX 2000                        // Set the Minimum Speed in microseconds
#define DirPin  8                             // Dir Schrittmotor
#define StepPin 7                             // Step Schrittmotor
#define EndPin  6                             // Endschalter
#define AnfPin  5                             // Anfangsschalter
#define ESCPin  4                             // Motordrehzahl
#define StartPin  3                           // Starttaster
#define StopPin  2                            // Stoptaster
#define RunningReturn false                   // Homing mit laufender Säge

ESC BL (ESCPin, SPEED_MIN, SPEED_MAX, 500);   // ESC_Name (ESC PIN, Minimum Value, Maximum Value, Default Speed, Arm Value)
int StepdelayMin = 500;                       // HIGH/LOW-Zeit min. Geschwindigkeit Schrittmotor
int StepdelayMax = 2000;                      // HIGH/LOW-Zeit max. Geschwindigkeit Schrittmotor
int StepSpeedup = 100;                        // Steigerung Rampe Schrittmotor Hochtouren
volatile bool StopFlag = false;               // Flag gesetzt durchStoptaster

//ISR
void NotAus()                                 // Unterbrechnung bei Stoptaster gedrückt (interrupt)
{
  BL.stop();                                  // Motor stoppen macht mehr sinn als langsam weiterlaufen zu lassen IMHO
  StopFlag = true;                            // Stop Flag setzen
}

void setup()
{
  pinMode (ESCPin, OUTPUT);                                         // PIN ESC Motorspeed
  pinMode (DirPin, OUTPUT);                                         // PIN Dir Schrittmotor
  pinMode (StepPin, OUTPUT);                                        // PIN Step Schrittmotor
  pinMode (EndPin, INPUT_PULLUP);                                   // PIN Endschalter
  pinMode (AnfPin, INPUT_PULLUP);                                   // PIN Anfangsschalter
  pinMode (StopPin, INPUT_PULLUP);                                  // PIN Stoptaster
  attachInterrupt(digitalPinToInterrupt(StopPin), NotAus, FALLING); // PIN 2 StopPin interrupt aktiviert
}

void SM_Fahr(const int &Pin)                        // no delay version; Pin ist der zu überwachende Endschalter
{
  int StepInc = StepdelayMax;                       // langsamste Geschwindigkeit (ww mit erster erhöhung?)
  unsigned long StepTime = millis() + StepdelayMax; // Zeitpunkt für ersten Schritt festlegen
  while (digitalRead(Pin) == HIGH)                  // Endschalter noch nicht erreicht
  {
    while (millis() < StepTime)                     // warten auf den Zeitpunkt 2 sekunden find ich aber arg viel!!
    {
      if (StopFlag)                                 // auch beim Warten auf NotAus hören!
        return;                                     // falls: BEIDE Schleifen unterbrechen also raus hier
    }
    digitalWrite(StepPin, !digitalRead(StepPin));   // einen Schritt tun
    if (StepInc > StepdelayMin)
      StepInc -= StepSpeedup;                       // Schrittmotor beschleunigen falls nötig
    StepTime += StepInc;                            // Zeitpunkt für nächsten Schritt festlegen
  }
}

void BL_speed(bool increase)                        // das geht mit einer Funktion und einem Parameter
{
  unsigned int spd_diff = SPEED_MAX - SPEED_MIN;    // der Unterscheid zwischen min und max ist interessant
  for (unsigned int i = 0; i <= spd_diff; i += 10)  // dahin wird gezählt ich hab die Schritte mal erweitert
  {
    if (StopFlag)                                   // Raus hier bei NotAus
      break;
    if (increase)                                   // welche Richtung
      BL.speed(SPEED_MIN + i);                      // increase (min +  diff)
    else
      BL.speed(SPEED_MAX - i);                      // decrease (max - diff)
    delay(10);                                      // den delay würd ich mir sparen fast.. aber nundenn
  }
}

void loop()
{
  if (digitalRead(StartPin) == LOW)                                    // wenn Starttaste gedrueckt geht`s los
  {
    StopFlag = false;                                                  // StopFlag löschen sonst könnte es klemmen
    if(RunningReturn)                                                  // wird im define geklärt ob mit laufender Säge zurückgefahren wird oder nicht
    {
        BL.arm();                                                      // ESC 'bewaffnen'
        BL_speed(true);                                                // und Säge anwerfen
    }
    if ((digitalRead(AnfPin) == HIGH) && (digitalRead(EndPin) == HIGH))// wenn Anfangspos. nicht erreicht zurück auf Start
    {
      digitalWrite(DirPin, LOW);                                       // DirPin 'rückwärts' setzen
      SM_Fahr(AnfPin);                                                 // Fahren zum Endschalter der Anfangsposition
    }
    if(!RunningReturn)                                                 // wird im define geklärt ob mit laufender Säge zurückgefahren wird oder nicht
    {
        BL.arm();                                                      // ESC 'bewaffnen'
        BL_speed(true);                                                // und Säge anwerfen
    }
    // zum Ende
    digitalWrite(DirPin, HIGH);                                        // DirPin 'vorwärts' setzen
    SM_Fahr(EndPin);                                                   // Fahren zum Endschalter der Endposition
    // wieder auf Anfang
    digitalWrite(DirPin, LOW);                                         // DirPin 'rückwärts' setzen
    SM_Fahr(AnfPin);                                                   // Fahren zum Endschalter der Anfangsposition

    BL_speed(false);                                                   // Säge langsam anhalten
    BL.stop();                                                         // und wieder abschalten
  }
}

'sid

von Jens R. (homerqlb)


Bewertung
-2 lesenswert
nicht lesenswert
sid schrieb:
> Deine Benennungen sind echt verwirrend für mich

Ja, ich hab den Dingen einfach Namen gegeben. Ich kenne mich da nicht 
mit dem Programmierknigge aus, aber wie ich sehe, hast du ja doch 
verstanden, was ich will.
Die ESC.h ist die richtige, hab das verwechselt mit der Anleitung.
Ich werde mir dein Programm mal ausgiebig vornehmen. Ich stecke ja nich 
in den Babyschuhen, das ist für mich schon höhere Programmierkunst, aber 
in den letzten Wochen habe ich schon mal eine Menge dazugelernt. Schade, 
dass ich den Code nicht alleine hingekriegt habe. Aber ich will ganz 
erlich sein, es bleibt ein Abstecher ins Programmieren eines µC. Wer 
weiß, ob ich mal wieder so ein Projekt anvisiere.
Noch eine Frage, du verwendest jetzt aber auch millis() ..., anstatt 
delay, obwohl du davon eigentlich abgeraten hast, wenn ich mich recht 
entsinne. Was ist denn nun so schlimm am `delay`.
Der Notaus läuft doch trotzdem im Hintergrund und wenn der µC gerade 
auch nichts tun soll, warum lassen wir ihn dann nicht auch ein bisschen 
ausruhen?
Danke für deine Mühe.
Ich werde die Sache im Versuchsaufbau testen.
Ach, da war noch was. Mir ist gerade eingefallen, dass es besser wäre, 
wenn man zum Starten 2 Tasten betätigt, aber das kriege ich vielleich 
selbst gebacken.

von sid (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Jens R. schrieb:
> Noch eine Frage, du verwendest jetzt aber auch millis() ..., anstatt
> delay, obwohl du davon eigentlich abgeraten hast, wenn ich mich recht
> entsinne. Was ist denn nun so schlimm am `delay`.
> Der Notaus läuft doch trotzdem im Hintergrund und wenn der µC gerade
> auch nichts tun soll, warum lassen wir ihn dann nicht auch ein bisschen
> ausruhen?

Wollt nur, dass Du für beides eine Beispiel hast..
ich mag delay normalerweise nicht so gerne, da es eben allen 
Programmablauf blockiert.

ein wait mit millis ist fast immer sinnvoller (nur eben nicht ohne 
Tücken)
Da ich aber nicht glaube, dass Deine Säge 39Tage nonstop läuft seh ich 
kein wirkliches Problem darin eine Zeitgesteuerte Warteschleife zu 
nutzen statt eines delays,
vor allem weil sie  so wie gesagt schneller auf den Notaus Befehl 
reagiert
(effektiv wird bei Dir keine Zeile Programm weniger oder mehr 
ausgeführt, es geht also wirklich um millisekunden an Unterschied)

Es ist nur eine formal Andere Lösung.
Wenn Du weiter dran arbeitest, dann könnte sich das ggf ändern;
und dann kann das eine oder andere besser sein

Ob Du so
void SM_Fahr(const int &Pin)                        // no delay version; Pin ist der zu überwachende Endschalter
{
  int StepInc = StepdelayMax;                       // langsamste Geschwindigkeit (ww mit erster erhöhung?)
  unsigned long StepTime = millis() + StepdelayMax; // Zeitpunkt für ersten Schritt festlegen
  while (digitalRead(Pin) == HIGH)                  // Endschalter noch nicht erreicht
  {
    while (millis() < StepTime)                     // warten auf den Zeitpunkt 2 sekunden find ich aber arg viel!!
    {
      if (StopFlag)                                 // auch beim Warten auf NotAus hören!
        return;                                     // falls: BEIDE Schleifen unterbrechen also raus hier
    }
    digitalWrite(StepPin, !digitalRead(StepPin));   // einen Schritt tun
    if (StepInc > StepdelayMin)
      StepInc -= StepSpeedup;                       // Schrittmotor beschleunigen falls nötig
    StepTime += StepInc;                            // Zeitpunkt für nächsten Schritt festlegen
  }
}

oder so
void SM_Fahr(const int &Pin)                        // delay version; Pin ist der zu überwachende Endschalter
{
  int StepTime = StepdelayMax;                      // Wartezeit für ersten Schritt festlegen
  while (digitalRead(Pin) == HIGH)                  // Endschalter noch nicht erreicht
  {
  delay(StepTime);                                // Warten
    if (StopFlag)                                   // nach dem Warten aufs NotAus hören!
        break;
    digitalWrite(StepPin, !digitalRead(StepPin));   // einen Schritt tun
    if (StepTime > StepdelayMin)
      StepTime -= StepSpeedup;                       // Schrittmotor beschleunigen falls nötig
  }
}

wartest ist im Moment noch völlig egal;
sei eben nur 'informiert', daß Beides Vor- und Nachteile haben kann ;)

wie Du siehst ist es auch egal WO in der schleife das delay 
stattfindet;
wichtig ist nur, dass zwischen dem überwachen des Notaus-Flags und dem 
eigentlichen Schritt (toggle des StepPins) möglichst keine Zeit vergeht.
(also den delay nicht dazwischen!)

Zwei taster geht auch;
am einfachsten dann als NO (normally open) und in Reihe an einem Pin
erst wenn beide tasten gedrückt sind wird die Verbindung von Pin und GND 
hergestellt und der Pin ist LOW
bei nur einer Taste bleibt die andere getrennt und der internal Pullup 
gewinnt ;)

'sid

von Jens R. (homerqlb)


Bewertung
0 lesenswert
nicht lesenswert
So, ich habe den Versuchsaufbau endlich fertig und ausprobiert. 
Natürlich funktionierte es nicht wie gewollt. Der Schrittmotor rast 
gleich zu Beginn los ohne Tastendruck. Es fehlte der pinMode für den 
Starttaster mit dem Pullup. Ich nehme an, der Pin war undefiniert LOW 
also dauergedrückt. Jetzt funktioniert es von der Schalterei glaube ich 
korrekt. Nur der BL-Motor springt nicht an. Der Fahrtregler, eigentlich 
ist es ein Flugregler, piept wie wild und geht wohl in den 
Programmiermodus. Hier muß er beim Einschalten denke ich wie beim Modell 
in Nullstellung sein. Das klappt noch nicht.
Eine Frage:

sid schrieb:
> if(RunningReturn)                                                  //
> wird im define geklärt ob mit laufender Säge zurückgefahren wird oder
> nicht
>     {
>         BL.arm();
> // ESC 'bewaffnen'
>         BL_speed(true);
> // und Säge anwerfen
>     }

Muß das nicht nach

sid schrieb:
> if ((digitalRead(AnfPin) == HIGH) && (digitalRead(EndPin) == HIGH))//
> wenn Anfangspos. nicht erreicht zurück auf Start

stehen?

von Jens R. (homerqlb)


Bewertung
-2 lesenswert
nicht lesenswert
sid schrieb:
> while (millis() < StepTime)                     // warten auf den
> Zeitpunkt 2 sekunden find ich aber arg viel!!

Ach ja, das sind Mikrosekunden!

von sid (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Jens R. schrieb:
> Muß das nicht nach
>
> sid schrieb:
>> if ((digitalRead(AnfPin) == HIGH) && (digitalRead(EndPin) == HIGH))//
>> wenn Anfangspos. nicht erreicht zurück auf Start
>
> stehen?

ÖHm nee wie gesagt nicht wenn Du mit laufender Säge in Nullstellung 
willst,
wenn nicht dann schon, deswegen steht da ja auch:

sid schrieb:
>
...if(RunningReturn)                                                  // 
> wird im define geklärt ob mit laufender Säge zurückgefahren wird oder 
> nicht
>     {
>         BL.arm(); 
> // ESC 'bewaffnen'
>         BL_speed(true); 
> // und Säge anwerfen
>     }
>     if ((digitalRead(AnfPin) == HIGH) && (digitalRead(EndPin) == 
> HIGH))// wenn Anfangspos. nicht erreicht zurück auf Start
>     {
>       digitalWrite(DirPin, LOW); 
> // DirPin 'rückwärts' setzen
>       SM_Fahr(AnfPin); 
> // Fahren zum Endschalter der Anfangsposition
>     }
>     if(!RunningReturn) 
> // wird im define geklärt ob mit laufender Säge zurückgefahren wird oder 
> nicht
>     {
>         BL.arm(); 
> // ESC 'bewaffnen'
>         BL_speed(true); 
> // und Säge anwerfen
>     }...

was dein controller für einen Befehl wann wie erwartet weiss nur das 
Datenblatt.
Aber ich schätze wenn Du es auf 1000,2000,500 gelassen hast sollte das 
eigentlich passen.

wenn er dauerpiept, ist meistens der arm value zu hoch (haste den wieder 
auf 1000 gesetzt?) und der controller vermutet ein throttle signal beim 
einschalten und mault.
programmier modus halte ich für unwahrscheinlich.

'sid

von Jens R. (homerqlb)


Bewertung
-1 lesenswert
nicht lesenswert
sid schrieb:
> wenn er dauerpiept, ist meistens der arm value zu hoch (haste den wieder
> auf 1000 gesetzt?) und der controller vermutet ein throttle signal beim
> einschalten und mault.

Ja da liegt wohl der Hase im Pfeffer. Das Programm habe ich 1 zu 1 von 
dir übernommen, nur den pinMode für den StartPin eingebaut.
Ich habe mir nochmal das Beispiel ESC_Ramp draufgespielt, da 
funktioniert es.
dort ist die Beschleunigung so geschrieben:
for (oESC = SPEED_MIN; oESC <= SPEED_MAX; oESC += 1) {  // goes from 1000 microseconds to 2000 microseconds
    myESC.speed(oESC);                                    // tell ESC to go to the oESC speed value
    delay(10);                                            // waits 10ms for the ESC to reach speed
  }
Ich denke es fehlt:
delay(10);                                            // waits 10ms for 
the ESC to reach speed
sonst pfeifft er hoch auf Max Speed und der Controller denkt 
Vollausschlag, also Programmiermodus.
Das ist nur meine Vermutung, aber ich weiß nicht, wie ich das in dein 
sonst bisher gut funktionierendes Programm einflechten kann.

von Jens R. (homerqlb)


Bewertung
-1 lesenswert
nicht lesenswert
Jens R. schrieb:
> Ich denke es fehlt:
> delay(10);                                            // waits 10ms for

Oh ich seh gerade, der delay ist ja doch drin.
Na jedenfalls funktioniert das ESC_Ramp mit meinem Controller.
Vielleicht hast du noch eine Ahnung, woran es liegt?

von Jens R. (homerqlb)


Bewertung
-1 lesenswert
nicht lesenswert
Oh! ich habe jetzt schon 2 zwei Anti-Fans.
Danke dafür!
Leider hat der Virus jetzt auch den momentan einzigen Helfer `sid` 
erwischt.
Es tut mir leid, das war nicht meine Absicht, dich mit dem 
Negativbewertungsvirus, kurz NBV-20 (ist das korrekt?) anzustecken. Ich 
hätte beim Schreiben wohl besser Mundschutz, oder Schal oder was weiß 
ich tragen sollen, wie es unsere Führung uns aufgetragen hat.
Ich habe mich nochmal mit sid`s Programm auseinandergesetzt und bin beim
"void BL_speed" hängen geblieben. so habe ich auch gleich noch etwas 
über die Übergabe von Variablen in Unterprogramme gelernt.

sid schrieb:
> for (unsigned int i = 0; i <= spd_diff; i += 10)  // dahin wird gezählt
> ich hab die Schritte mal erweitert

Da habe ich den Wert wie im Beispiel den "i+=10" wieder auf 1 gesetzt.
Jetzt läuft die Säge auch an.
Bei einem "Notaus" stopt der Motor sofort, aber es kommt auch gleich die 
Überlast des PC-Netzteils. Das ist aber auch der Sinn eines Notaus: 
schnellstmöglicher Stillstand!
Ich werde weiter experimentieren und melde mich wieder, wenn es Probleme 
gibt.
Danke an alle!
Bis dahin, bleibt gesund und helft weiter solchen Idioten wie mir, ihre 
sinnlosen Projekte umsetzen können.
Gruß Jens

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.