PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Programm ablauf langsam



fredyxx
28.08.2016, 10:47
Hallo,

ich habe ein Baggermodell mit Arduino MEGA und 6 Schrittmotoren. Fast alles klappt zZ prima mit einer Ausnahme.
Für die Schrittmotoransteuerung habe ich ein selbsterstelltes Unterprogramm geschrieben, dessen Aufruf für einen Motor z.B. so aussieht:

M1_drive(41, 43, 45, 47, n, 30, 0); // 41, 43, 45, 47 sind die Ausgänge, n = Anzahl der Umdrehungen,
// 30 = Anzahl der Umdrehungen/min; 0 = Drehrichtung

Mit den Geschwindigkeiten, die die Zahnstangenantriebe fahren, bin ich für den normalen Ablauf zufrieden. Es gibt jedoch eine Unterprogramm "Justierung" mit dem ich nach einander alle Antriebe in eine definierte Ausgangsstellung fahren kann. Bei dieser Betriebsart schleichen die Antriebe jedoch nur, auch wenn ich den Parameter für die U/min in den entsprechenden Aufrufen vergrößere. Die Unterprogramme Mx_drive benutze ich in jedem Fall, jedoch für jeden Motor ein separates.
Zunächst hatte ich die Library Bounce2 in Verdacht, mit der ich das Prellen eines Tasters, der mit Erreichen der Grundstellung eines Antriebs betätigt wird, unterdrücken will. Die Einstellung von 1 ms reichte dafür aus. Aber auch wenn ich 100 ms einstellte, liefen die Antriebe nicht langsamer, so dass ich meine, dass diese Library den normalen Programmzyklus nicht verzögert. Oder liege ich da falsch?

Evtl. fällt jemandem spontan auf, was die Ursache für diese unterschiedlichen Geschwindigkeiten sein könnte.

Ich habe den Teil des Codes für Motor1 aus dem Unterprogramm Justierung angefügt und ein Bild des entsprechenden Flussdiagramms.


// ************************************** UP Justierung **************************************

void Justierung() {
static boolean M1_fertig = false;
static boolean M2_fertig = false;
static boolean M3_fertig = false;
static boolean M4_fertig = false;
static boolean M5_fertig = false;
static boolean M6_fertig = false;
static boolean M1_laeuft = false;
static boolean M2_laeuft = false;
static boolean M3_laeuft = false;
static boolean M4_laeuft = false;
static boolean M5_laeuft = false;
static boolean M6_laeuft = false;
static boolean Z_EIN; // true, solange Timer 1 läuft


if (M1_fertig == true) {


goto M2_Sprung; // M1 wird übersprungen
}

if (JustPin == HIGH) {
M1_laeuft = true;

M1_drive(41, 43, 45, 47, 30, 3, 1); // 41, 43, 45, 47, Mx_n, Mx_v, Mx_dir ; für den MEGA


return;

} // *********** ENDE if (JustPin == HIGH)


if (Zeit_EIN(M1_laeuft) == true) { // Aufruf des UPs Zeit_EIN(), das die Zeit startet, in der JustPin LOW sein muss, damit eine Motor übersprungen wird.

return; // Sprung aus UP Justierung
}



timer1.disable(zeitId); // Timer1 löschen

M1_fertig = true; // wenn Auftrag vom Hauptprogramm erledigt ist
M1_Start == true;
Zeitueberlauf = false; // eigenes Zeitsignal löschen
TimerAktiv = false;
lzahn1_alt = 1.0;

digitalWrite(41, LOW); // alle LOW, damit der Motor im Stillstand stromlos ist.
digitalWrite(43, LOW);
digitalWrite(45, LOW);
digitalWrite(47, LOW);




M2_Sprung: // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ab hier Start Motor 2


31958

Mir ist klar, dass das mit diesen Informationen keine einfache Frage ist.

Welche Möglichkeiten kennt ihr, den Verursacher zu finden?

Noch zur Erklärung:
Zahnstangengeschwindigkeit von 13 mm/s ist ok
Bei Justierung nur ca. 2 mm/s

vG

fredyxx

i_make_it
28.08.2016, 11:16
Ich sehe Spagetticode (GOTOaus einem UP das mit RETURN Verlassen werden soll)



void Justierung() {

if (M1_fertig == true) {
goto M2_Sprung; // M1 wird übersprungen
}

if (JustPin == HIGH) {
return;
} // *********** ENDE if (JustPin == HIGH)

return; // Sprung aus UP Justierung
}

M2_Sprung:


Was sagt denn Dein Stack und dein Heap zu dem Konstrukt? läuft da nicht was auf Dauer über oder hast Du es noch nicht lang genug laufen lasse?
Du rufst ja Justierung() auf und jedesmal wenn Du mit einem GOTO rausspringst verlässt DU es nicht mehr (zumindest nicht für den Prozessor).
Wenn schon GOTO dann definitiv nur innerhalb der Funktion. Verlassen solltest Du die Funktion aber mit einer korrekten Abbruchbedingung und einem Rückgabewert, der in der Hauptschleife verarbeitet wird und zum Aufruf von dem was nach M2_Sprung kommt, führt.

Um zu verstehen wann man GOTO einsetzen kann und wann es gfährlich ist, müsste jeder eigentlich erst mal Assembler lernen. Da gibt es nämlich nur GOTO (Jump / Farjump) Allerdings muß man sich da auch selbst darum kümmern Register zu retten, Stackpointer und den Heap zu verwalten.
Hochsprachen nehmen einem das ales ab, haben aber oft noch das GOTO (JUMP) drin.
Ohne das verständniss davon was im Hintergrund läuft, kann GOTO an der falschen Stelle und falsch eingesetzt zu einem (für das Programm) tödlichen Bumerang werden.
Nicht umsonst ist die Fraktion entstanden die GOTO generell verteufelt.
Als Anfänger sollte man GOTO meiden bis man verstanden hat was wann wo geschieht und man in der Lage ist zu erkennen wo ein GOTO schlanken Code erzeugt und wo es Chaos und Abstürze verursacht.

Peter(TOO)
28.08.2016, 11:23
Hallo,

Kann es sein, dass dein Unterprogramm dauernd aufgerufen wird und somit der Motor dauernd gestartet wird?
M1_laeuft wird zwar gesetzt, aber wo wird es abgefragt, bzw. was bewirkt es?

M1_drive() sollte nicht aufgerufen werden, wenn M1_lauft gesetzt ist.

MfG Peter(TOO)

fredyxx
28.08.2016, 11:45
Die Sprungfunktion täuscht hier, weil in dem Unterprogramm Justierung noch 5 mal so ein Programmteil für die anderen Motoren existiert (den Teil wollte ich euch ersparen) und ich springe dann nur innerhalb des UP's zum nächsten Motor, wenn der vorhergehende seine Position erreicht hat.
Was sind Stack und Heap?
Das Programm arbeitet ja auch sonst schnell und ordnungsgemäß, wenn ich mit der Schaufel über 2 Gelenke des Baggerarms eine konkrete xy-Position anfahre.

vG

fredyxx

- - - Aktualisiert - - -


Hallo,

Kann es sein, dass dein Unterprogramm dauernd aufgerufen wird und somit der Motor dauernd gestartet wird?
M1_laeuft wird zwar gesetzt, aber wo wird es abgefragt, bzw. was bewirkt es?

M1_drive() sollte nicht aufgerufen werden, wenn M1_lauft gesetzt ist.

MfG Peter(TOO)

Das ist nötig, weil in diesem UP festgestellt wird, ob die 4 Ausgänge für den Stepper verändert werden müssen(nächster Schritt) . Wenn die Schrittdauer noch nicht erreicht ist, wird das UP sofort wieder verlassen.

Diese Lösung habe ich nach der Diskussion in diesem Thread für mich gewählt und bin bis auf das Justieren auch damit zufrieden.

https://www.roboternetz.de/community/threads/69306-Suche-nach-Stepper-Library/page2?highlight=fredyxx



vG

fredyxx

Mxt
28.08.2016, 12:00
Du rufst ja Justierung() auf und jedesmal wenn Du mit einem GOTO rausspringst verlässt DU es nicht mehr (zumindest nicht für den Prozessor).

Das kann es eigentlich nicht sein. Arduino ist C++ und das erlaubt nur Sprünge innerhalb einer Funktion. Trotzdem ist die Verwendung von goto zu dem hier verwendeten Zweck ganz allgemein schlechter Stil.

HaWe
28.08.2016, 12:44
ich finde den ganzen Hinweis/Post mit dem Sprung aus der Funktion heraus für gar nicht nachvollziehbar:
Sprung und Sprungadresse liegen doch innerhalb ein und derselben Funktion, oder etwa nicht?
Ansonsten müsste auch der Arduino-Compiler meckern, was er aber offenbar doch nicht tut. Dann aber hätte es nur zur Folge, dass der Sprung komplett rausoptimiert wird, denn Sprünge aus einer Funktion heraus gehen ja gar nicht, wie mxt richtig angemerkt hat.
Muss also andere Gründe haben...


goto allerdings finde ich persönlich für weder schlechten noch guten Stil, es vereinfacht oft komplizierte Abbruchbedingungen und ist daher ebenso legitim wie if, for, while, case (was ja auch wieder nur ein Sprung ist). Wer goto benutzen will, soll es tun, manchmal macht es Dinge sogar übersichtlicher.

Peter(TOO)
28.08.2016, 12:51
Hallo fredyxx,

Das ist nötig, weil in diesem UP festgestellt wird, ob die 4 Ausgänge für den Stepper verändert werden müssen(nächster Schritt) . Wenn die Schrittdauer noch nicht erreicht ist, wird das UP sofort wieder verlassen.

Diese Lösung habe ich nach der Diskussion in diesem Thread für mich gewählt und bin bis auf das Justieren auch damit zufrieden.
Tja, woher weiss man dies, wenn man den Code nicht kennt?

Und wie funktioniert Zeit_EIN()?
Kehrt die Funktion sofort zurück oder erst wenn die Zeit abgelaufen ist?

MfG Peter(TOO)

fredyxx
28.08.2016, 13:29
Das kann es eigentlich nicht sein. Arduino ist C++ und das erlaubt nur Sprünge innerhalb einer Funktion.

Wenn Funktion = Unterprogramm ist, dann mache ich das auch nicht anders.


Trotzdem ist die Verwendung von goto zu dem hier verwendeten Zweck ganz allgemein schlechter Stil.

Ich denke mit diesen unvollständigen Informationen zu dem Gesamtprogramm ist das nicht zu beurteilen.

- - - Aktualisiert - - -


Hallo fredyxx,

Tja, woher weiss man dies, wenn man den Code nicht kennt?

MfG Peter(TOO)

Ja, sehe ich ein. Aber den vollständigen Code von über 2000 Zeilen möchte ich keinem zumuten.


Hallo fredyxx,
Und wie funktioniert Zeit_EIN()?
Kehrt die Funktion sofort zurück oder erst wenn die Zeit abgelaufen ist?
MfG Peter(TOO)

Kommt mit Sicherheit sofort zurück, weil ich den jeweiligen Motor mit einem Taster vor Ablauf der Zeit stoppen kann. Also muss der Zyklus in der Zeit weiter laufen.

vG

fredyxx

Mxt
28.08.2016, 13:33
Ich denke mit diesen unvollständigen Informationen zu dem Gesamtprogramm ist das nicht zu beurteilen.
C++ Erfinder Stroustrup schreibt dazu (in "The C++ Programming Language", Kap. 9.6)

The goto has few uses in general high level programming, but it can be very useful when C++ code is generated by a program rather than written directly by a person; for example, gotos can be used in a parser generated from a gramar by a parser generator.

HaWe
28.08.2016, 13:49
also wenn Code langsam läuft, und es an dem geposteten Snippet nicht liegt (was noch zu beweisen wäre), dann muss es zwangsweise irgendwo am/im restlichen Programm liegen,
- doch dazu muss es man kennen, und mag es noch so groß oder klein sein ;)

Mxt
28.08.2016, 14:22
Auf jeden Fall sieht man schon mal, dass die goto Konstruktion sowas in der Art darstellen soll


void Justierung() {
static uint8_t motor = 1;

switch(motor) {
case 1:
if (JustPin == HIGH) {
// ...
}

// ...

motor++;

// ...
break;
case 2:
// Ähnlich für 2. Motor

case 3:
case 4:
case 5:
case 6:

default:
// irgendwas tun, wenn alle Motoren fertig
break;
}
Dabei wird immer noch viel Code dupliziert. Wahrscheinlich könnte man das, was in einem case-Block steht in eine oder mehrere Funktionen packen, die man dann aus jeden Block mit anderen Parametern aufruft.

Was mir beim Durchsehen aufgefallen ist

if (JustPin == HIGH)
wie wird JustPin geändert ?

Außerdem scheint da ja ein Timer zugange zu sein. Wahrscheinlich wird da was öfter oder in anderer Reihenfolge aufgerufen, als erwartet.

fredyxx
28.08.2016, 16:28
also wenn Code langsam läuft, und es an dem geposteten Snippet nicht liegt (was noch zu beweisen wäre), dann muss es zwangsweise irgendwo am/im restlichen Programm liegen,
- doch dazu muss es man kennen, und mag es noch so groß oder klein sein ;)

OK! Daran soll es nicht scheitern. Ich habe eine abgespeckte Version des gesamten Programms gemacht, in dem nur 2 Motore justiert werden sollen und der Programmteil, mit dem die Motore ihre brauchbare Geschwindigkeit fahren, ist entfernt. Der "Langsameffekt" ist jedoch noch vorhanden. Außerdem habe ich noch das Flussdiagramm vom M2_drive angehängt. M1_drive ist entsprechend genauso.

Bei der Abspeckerei ist mir aufgefallen, dass ich in dem Teil, der funktioniert, die Library "SimpleTimer" nicht verwende. Kann der diese zusätzliche Verzögerung evtl. verursachen?

Evtl. sind noch unschädliche Reste oder Kommentare von den anderen Motoren zu finden!!


/* Dieses Programm steuert den Bagger ohne jegliche Sensoren.
* ********************Die Steppersoftware ist selber gemacht.*******************************
***** es sind die Bagger - Programme
***** STOP und
***** Justierung
***** Motor 2 fahren >>>> mit Schaufelbewegung
***** funktionsfähig

* *********** um die PullUp-Widerstände zu nutzen, LOW = Aktivierung der Funktion *****************


- Nr.1 (PIN 2) Stillstand
- Nr.2 (PIN 3) Justierung
- Nr.3 (PIN 4) eine Bewegung von M2 mit folgender Schaufelbewegung
- Nr.4 (PIN 5) eine Bewegung von M3 mit folgender Schaufelbewegung
- Nr.5 (PIN 6) eine Koordinate anfahren
- Nr.6 (PIN 7) einen "LKW" beladen

SUCH-ZIELE: #include void M1_drive void M2_drive void Zeitablauf1()
boolean Zeit_EIN void Justierung() void setup void loop()


*/


#include <SimpleTimer.h> // einbinden der Library

SimpleTimer timer1; // Benennung der Timer


#include <Bounce2.h> // einbinden der Library für die Unterdrückung des Kontaktentprellens
Bounce debouncer = Bounce();

float microsalt;

boolean MK1_1; // Variable für die Eingänge des Mäusklaviers 1; schalten gegen GND
boolean MK1_2; // sie sind aktiv bei LOW
boolean MK1_3;
boolean MK1_4;
boolean MK1_5;
boolean MK1_6;
boolean MK1_7;
boolean MK1_8;


boolean JustM3var = LOW; // wird erst HIGH, wenn JustPin wieder HIGH ist; Funktion Fangschaltung
boolean M1solldrehen = true; // für UP Justierung
boolean M2solldrehen = true; // für UP Justierung
boolean M3solldrehen = false; // für UP Justierung
boolean Zeitueberlauf = false; // Wird false, wenn Zeit von SimpleTimer 1 abgelaufen ist


boolean Zyklus_fahren = true;

int JustPin_roh = 53; // mit digital Eingang 53 wird beim Justieren die jeweilige Motorbewegung gestoppt
int JustPin; // diese Variable nimmt das Ergebnis nach der Prellunterdrückung an

int zeitId; // für den SimpleTimer


//++++++++++++++++++ für weitere UPs

boolean M1_fertig = false;
boolean M1_Start = true;
int Zyklus_M1 = 1;
float lzahn1_alt = 1.0; // Ausfahrlänge von Zahnstange 1 nach Justierung 1
float lzahn1; // Ausfahrlänge von Zahnstange 1


boolean M2_fertig = false;
boolean M2_Start = true;
int Zyklus_M2 = 1;
float lzahn2_alt = 98.0; // Ausfahrlänge von Zahnstange 2 nach Justierung 98
float lzahn2; // Ausfahrlänge von Zahnstange 2



boolean TimerAktiv = false;


//++++++++++++++++++++++++++++++++++




// ***************************** UP M1_drive ************************************************** ***************

void M1_drive (int p1, int p2, int p3, int p4, float n, int v, boolean dir) {
// n : Anzahl Umdrehungen; v in U/min; dir: 0 oder 1

static int M1_i;
static float M1_microsalt;
static float SPUsM1 = 1440.0; // entspricht etwa 1 U/min
static unsigned int Schrittdauer;
static unsigned int Schrittzahl = 1;
static unsigned int SchrittzahlEnd;



if ( M1_Start == true) { // wird nur beim 1. Aufruf des UPs erfüllt, wenn M1_Start = true

Schrittdauer = int(1000000.0 * 60.0 / (v * SPUsM1) ); // Ergebnis in us; 660 us =: 1515 Hz klappt noch als Minimum
//------------------------------------------- 10 U/min := 1464 us =: 683 Hz =: 0,16667 U/s =: 60 °/s


SchrittzahlEnd = n * SPUsM1;



M1_microsalt = micros();
M1_Start = false;
M1_i = 0;

} // ************ ENDE if ( M1_Start == true)


if (dir == 0 && (micros() - M1_microsalt) > Schrittdauer) { // Drehrichtung


switch (M1_i) { // es soll nur ein Schritt ausgeführt werden.

case 0:
M1_i = 1;
goto M1_0;
break;
case 1:
M1_i = 2;
goto M1_1;
break;
case 2:
M1_i = 3;
goto M1_2;
break;
case 3:
M1_i = 4;
goto M1_3;
break;
case 4:
M1_i = 5;
goto M1_4;
break;
case 5:
M1_i = 6;
goto M1_5;
break;
case 6:
M1_i = 7;
goto M1_6;
break;
case 7:
M1_i = 0;
goto M1_7;
break;

}

} // ************ ENDE if (dir == 0 && (micros() - M1_microsalt) > Schrittdauer)


else if (dir == 1 && (micros() - M1_microsalt) > Schrittdauer) { // Drehrichtung

switch (M1_i) { // es soll nur ein Schritt ausgeführt werden.

case 0:
M1_i = 1;
goto M1_7;
break;
case 1:
M1_i = 2;
goto M1_6;
break;
case 2:
M1_i = 3;
goto M1_5;
break;
case 3:
M1_i = 4;
goto M1_4;
break;
case 4:
M1_i = 5;
goto M1_3;
break;
case 5:
M1_i = 6;
goto M1_2;
break;
case 6:
M1_i = 7;
goto M1_1;
break;
case 7:
M1_i = 0;
goto M1_0;
break;

}





M1_0:

digitalWrite(p1, HIGH);
digitalWrite(p2, LOW);
digitalWrite(p3, LOW);
digitalWrite(p4, LOW);
goto M1_Schritt;

M1_1:

digitalWrite(p1, HIGH);
digitalWrite(p2, HIGH);
digitalWrite(p3, LOW);
digitalWrite(p4, LOW);
goto M1_Schritt;

M1_2:

digitalWrite(p1, LOW);
digitalWrite(p2, HIGH);
digitalWrite(p3, LOW);
digitalWrite(p4, LOW);
goto M1_Schritt;

M1_3:

digitalWrite(p1, LOW);
digitalWrite(p2, HIGH);
digitalWrite(p3, HIGH);
digitalWrite(p4, LOW);
goto M1_Schritt;

M1_4:

digitalWrite(p1, LOW);
digitalWrite(p2, LOW);
digitalWrite(p3, HIGH);
digitalWrite(p4, LOW);
goto M1_Schritt;

M1_5:

digitalWrite(p1, LOW);
digitalWrite(p2, LOW);
digitalWrite(p3, HIGH);
digitalWrite(p4, HIGH);
goto M1_Schritt;

M1_6:

digitalWrite(p1, LOW);
digitalWrite(p2, LOW);
digitalWrite(p3, LOW);
digitalWrite(p4, HIGH);
goto M1_Schritt;

M1_7:

digitalWrite(p1, HIGH);
digitalWrite(p2, LOW);
digitalWrite(p3, LOW);
digitalWrite(p4, HIGH);
goto M1_Schritt;


return;


M1_Schritt:


M1_microsalt = micros();

if ( Schrittzahl++ > SchrittzahlEnd) { // Der Auftrag vom aufrufenden Programm ist beendet


Schrittzahl = 0;

M1_fertig = true; // wenn Auftrag "M1_drive" erledigt ist

digitalWrite(p1, LOW); // alle LOW, damit der Motor im Stillstand stromlos ist.
digitalWrite(p2, LOW);
digitalWrite(p3, LOW);
digitalWrite(p4, LOW);

} // ********** ENDE if ( Schrittzahl++ == SchrittzahlEnd)

} // ************ ENDE else if (dir == 1 && (micros() - M1_microsalt) > Schrittdauer)



} //******************* ENDE UP M1_drive ************************************************** *****************************




// ***************************** UP M2_drive ************************************************** **************************

void M2_drive (int p1, int p2, int p3, int p4, float n, int v, boolean dir) {
// n : Anzahl Umdrehungen; v in U/min; dir: 0 oder 1

static int M2_i;
static float M2_microsalt;
static float SPUsM2 = 4096.0; // entspricht etwa 1 U/min
static unsigned int Schrittdauer;
static unsigned int Schrittzahl = 1;
static unsigned int SchrittzahlEnd;



if ( M2_Start == true) { // wird nur beim 1. Aufruf des UPs erfüllt, wenn M2_Start = true

Schrittdauer = int(1000000.0 * 60.0 / (v * SPUsM2) ); // Ergebnis in us; 660 us =: 1515 Hz klappt noch als Minimum
//------------------------------------------- 10 U/min := 1464 us =: 683 Hz =: 0,16667 U/s =: 60 °/s


SchrittzahlEnd = n * SPUsM2;


M2_microsalt = micros();
M2_Start = false;
M2_i = 0;

} // ************ ENDE if ( M2_Start == true)


if (dir == 0 && (micros() - M2_microsalt) > Schrittdauer) { // Drehrichtung


switch (M2_i) { // es soll nur ein Schritt ausgeführt werden.

case 0:
M2_i = 1;
goto M2_0;
break;
case 1:
M2_i = 2;
goto M2_1;
break;
case 2:
M2_i = 3;
goto M2_2;
break;
case 3:
M2_i = 4;
goto M2_3;
break;
case 4:
M2_i = 5;
goto M2_4;
break;
case 5:
M2_i = 6;
goto M2_5;
break;
case 6:
M2_i = 7;
goto M2_6;
break;
case 7:
M2_i = 0;
goto M2_7;
break;

}

} // ************ ENDE if (dir == 0 && (micros() - M2_microsalt) > Schrittdauer)


else if (dir == 1 && (micros() - M2_microsalt) > Schrittdauer) { // Drehrichtung

switch (M2_i) { // es soll nur ein Schritt ausgeführt werden.

case 0:
M2_i = 1;
goto M2_7;
break;
case 1:
M2_i = 2;
goto M2_6;
break;
case 2:
M2_i = 3;
goto M2_5;
break;
case 3:
M2_i = 4;
goto M2_4;
break;
case 4:
M2_i = 5;
goto M2_3;
break;
case 5:
M2_i = 6;
goto M2_2;
break;
case 6:
M2_i = 7;
goto M2_1;
break;
case 7:
M2_i = 0;
goto M2_0;
break;

}





M2_0:

digitalWrite(p1, HIGH);
digitalWrite(p2, LOW);
digitalWrite(p3, LOW);
digitalWrite(p4, LOW);
goto M2_Schritt;

M2_1:

digitalWrite(p1, HIGH);
digitalWrite(p2, HIGH);
digitalWrite(p3, LOW);
digitalWrite(p4, LOW);
goto M2_Schritt;

M2_2:

digitalWrite(p1, LOW);
digitalWrite(p2, HIGH);
digitalWrite(p3, LOW);
digitalWrite(p4, LOW);
goto M2_Schritt;

M2_3:

digitalWrite(p1, LOW);
digitalWrite(p2, HIGH);
digitalWrite(p3, HIGH);
digitalWrite(p4, LOW);
goto M2_Schritt;

M2_4:

digitalWrite(p1, LOW);
digitalWrite(p2, LOW);
digitalWrite(p3, HIGH);
digitalWrite(p4, LOW);
goto M2_Schritt;

M2_5:

digitalWrite(p1, LOW);
digitalWrite(p2, LOW);
digitalWrite(p3, HIGH);
digitalWrite(p4, HIGH);
goto M2_Schritt;

M2_6:

digitalWrite(p1, LOW);
digitalWrite(p2, LOW);
digitalWrite(p3, LOW);
digitalWrite(p4, HIGH);
goto M2_Schritt;

M2_7:

digitalWrite(p1, HIGH);
digitalWrite(p2, LOW);
digitalWrite(p3, LOW);
digitalWrite(p4, HIGH);
goto M2_Schritt;


return;


M2_Schritt:


M2_microsalt = micros();

if ( Schrittzahl++ > SchrittzahlEnd) { // Der Auftrag vom aufrufenden Programm ist beendet


Schrittzahl = 0;
// M2_Start = true; // nötig für den nächsten Auftrag ???????

M2_fertig = true; // wenn Auftrag "M2_drive" erledigt ist

digitalWrite(p1, LOW); // alle LOW, damit der Motor im Stillstand stromlos ist.
digitalWrite(p2, LOW);
digitalWrite(p3, LOW);
digitalWrite(p4, LOW);

} // ********** ENDE if ( Schrittzahl++ == SchrittzahlEnd)

} // ************ ENDE else if (dir == 1 && (micros() - M2_microsalt) > Schrittdauer)



} //******************* ENDE UP M2_drive ************************************************** ****************








//**************************** UP Zeitablauf1 ************************************************** ********
void Zeitablauf1() { // wird ausgeführt, wenn SimpleTimer timer 1 abgelaufen ist

Zeitueberlauf = true; //



} // *********** ENDE UP Zeitablauf1 ************************************************** **************




// ************************************** UP Zeit_EIN ************************************************** *

boolean Zeit_EIN (boolean Mx_laeuft ) { // Zeitueberlauf ist global deklariert

// static boolean TimerAktiv = false; // true, wenn Timer angestoßen ist


if (Mx_laeuft == true) {
return false;
}

if (TimerAktiv == true) {

if ( Zeitueberlauf == true) {
return false;
}
// ************ENDE if ( Zeitueberlauf == true)

else if (Zeitueberlauf == false) {

return true; // true, damit dann auch UP Justierung verlassen wird.
} // ************ENDE else (Timer1aktiv == true)

} // ***********ENDE if (TimerAktiv == true)

zeitId = timer1.setTimeout(3000, Zeitablauf1); // dieser Aufruf löscht sich nach einer Benutzung selber

TimerAktiv = true;

return true;

} // *********** ENDE UP Zeit_EIN ************************************************** *******************************





// ************************************** UP Justierung ************************************************** ****************

void Justierung() {
static boolean M1_fertig = false;
static boolean M2_fertig = false;

static boolean M1_laeuft = false;
static boolean M2_laeuft = false;

static boolean Z_EIN; // true, solange Timer 1 läuft


if (M1_fertig == true) { // ab hier Motor 1 justieren


goto M2_Sprung; // M1 wird übersprungen
}

if (JustPin == HIGH) {
M1_laeuft = true;

M1_drive(41, 43, 45, 47, 30, 3, 1); // 41, 43, 45, 47, Mx_n, Mx_v, Mx_dir ; für den MEGA
// Mx_n : Zahl Umdrehungen, die der M1 machen soll
// muss hier so hoch sein, dass Zahnstange bis zum Ende fahren kann

// geht ohne Belastung noch bis ? ; tatsächliche Geschwindigkeit aber ungenau
// gewünschte Richtung von Mx; 1 einfahren, 0 ausfahren


return;

} // *********** ENDE if (JustPin == HIGH)


if (Zeit_EIN(M1_laeuft) == true) { // Aufruf des UPs Zeit_EIN(), das die Zeit startet, in der JustPin LOW sein muss, damit eine Motor übersprungen wird.

return; // Sprung aus UP Justierung
}



timer1.disable(zeitId); // Timer1 löschen

M1_fertig = true; // wenn Auftrag vom Hauptprogramm erledigt ist
M1_Start == true;
Zeitueberlauf = false; // eigenes Zeitsignal löschen
TimerAktiv = false;
lzahn1_alt = 1.0;

digitalWrite(41, LOW); // alle LOW, damit der Motor im Stillstand stromlos ist.
digitalWrite(43, LOW);
digitalWrite(45, LOW);
digitalWrite(47, LOW);




M2_Sprung: // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ab hier Start Motor 2 justieren


if (M2_fertig == true) {

goto M3_Sprung; // M2 wird übersprungen
}

if (JustPin == HIGH) {
M2_laeuft = true;

M2_drive(22, 24, 26, 28, 20, 3, 0); // 22, 24, 26, 28, Mx_n, Mx_v, Mx_dir
// Mx_n : Zahl Umdrehungen, die der M2 machen soll
// muss hier so hoch sein, dass Zahnstange bis zum Ende fahren kann

// geht ohne Belastung noch bis 18 ; tatsächliche Geschwindigkeit aber ungenau
// gewünschte Richtung von Mx; 1 gegen Uhrzeiger CCW, 0 mit Uhrzeiger CW


return;

} // *********** ENDE if (JustPin == HIGH)


if (Zeit_EIN(M2_laeuft) == true) { // Aufruf des UPs Zeit_EIN(), das die Zeit startet, in der JustPin LOW sein muss, damit eine Motor übersprungen wird.

return; // Sprung aus UP Justierung

}



timer1.disable(zeitId); // Timer1 löschen

M2_fertig = true; // wenn Auftrag vom Hauptprogramm erledigt ist
M2_Start == true;
Zeitueberlauf = false; // eigenes Zeitsignal löschen
TimerAktiv = false;
lzahn2_alt = 98.0;

digitalWrite(22, LOW); // alle LOW, damit der Motor im Stillstand stromlos ist.
digitalWrite(24, LOW);
digitalWrite(26, LOW);
digitalWrite(28, LOW);



M3_Sprung: // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ab hier Start Motor 3

return;




} //************* ENDE UP Justierung ************************************************** *****************************






void setup() {

Serial.begin (250000); // diese Buadrate muss auch in der Konsole (Serieller Monitor) eingestellt sein
while (!Serial);

pinMode (JustPin_roh, INPUT); // wird nur im UP Justierung benötigt
digitalWrite(JustPin_roh, HIGH); //schaltet den PullUp-Widerstand ein

debouncer.attach(JustPin_roh); // für Prellunterdrückung von Pin 53
debouncer.interval(100); // interval in ms




pinMode (2, INPUT); // Pins als Eingänge deklarieren
pinMode (3, INPUT);
pinMode (4, INPUT);
pinMode (5, INPUT);
pinMode (6, INPUT);
pinMode (7, INPUT);
pinMode (8, INPUT);

pinMode (13, OUTPUT);
digitalWrite (13, LOW);


digitalWrite (2, HIGH); // schaltet die 20 kOhm PullUp-widerstände ein
digitalWrite (3, HIGH);
digitalWrite (4, HIGH);
digitalWrite (5, HIGH);
digitalWrite (6, HIGH);
digitalWrite (7, HIGH);
digitalWrite (8, HIGH);


pinMode (41, OUTPUT); // M1
pinMode (43, OUTPUT);
pinMode (45, OUTPUT);
pinMode (47, OUTPUT);

pinMode (22, OUTPUT); // M2
pinMode (24, OUTPUT);
pinMode (26, OUTPUT);
pinMode (28, OUTPUT);

pinMode (32, OUTPUT); // M3
pinMode (34, OUTPUT);
pinMode (36, OUTPUT);
pinMode (38, OUTPUT);

pinMode (42, OUTPUT); // M4
pinMode (44, OUTPUT);
pinMode (46, OUTPUT);
pinMode (48, OUTPUT);

pinMode (31, OUTPUT); // M5
pinMode (33, OUTPUT);
pinMode (35, OUTPUT);
pinMode (37, OUTPUT);


}

void loop() {


// für die Prellunterdrückung des Justierstopeingangs
debouncer.update(); // aktualisiert den Bouncezustand
JustPin = debouncer.read(); // übergibt den aktualisierten Wert an die Variable JustPin. Diese wird im weiteren Programm verwendet





MK1_1 = HIGH; //digitalRead(2); // STOP > die Variablen MK.. erhalten die Zustände der Eingänge
MK1_2 = LOW; //digitalRead(3); // Justieren; sie sind aktiv bei LOW
MK1_3 = HIGH; //digitalRead(4); // M1 und M2 fahren
MK1_4 = HIGH; //digitalRead(5); // M1 und M3 fahren
MK1_5 = HIGH; //digitalRead(6); // xy anfahren float HP_X1
MK1_6 = HIGH; //digitalRead(7); // LKW beladen
MK1_7 = HIGH; //digitalRead(8);
MK1_8 = HIGH; //digitalRead(9);


if (MK1_1 == LOW ) { //STOP
// Zyklus_M2 = 1 ; // d.h. M2 soll den 1. Zyklus fahren
}
else if (MK1_2 == LOW && MK1_1 == HIGH ) { // Justierung
Justierung(); // Programm 2: Justierung
}

LOOP_END:


timer1.run();



} //************* ENDE loop31961

Mxt
28.08.2016, 16:59
Ok, jetzt kann man es beurteilen und es sieht so grottig aus, wie erwartet.

Ich habe nach erstem Drübersehen einen Verdacht:

Dieses "float microsalt" sieht verdächtig aus. Der Rückgabewert von micros() ist nicht float, sondern unsigned long. Bei allen diesen Berechnungen treten auf jeden Fall Fehler auf, da float nicht so viele gültige Stellen hat.

fredyxx
28.08.2016, 17:11
Ok, jetzt kann man es beurteilen und es sieht so grottig aus, wie erwartet.

Ich habe nach erstem Drübersehen einen Verdacht:

Dieses "float microsalt" sieht verdächtig aus. Der Rückgabewert von micros() ist nicht float, sondern unsigned long. Bei allen diesen Berechnungen treten auf jeden Fall Fehler auf, da float nicht so viele gültige Stellen hat.


Ist grottig ein Kompliment? Kann mich aber nicht erschüttern, da dies mein erstes Projekt mit dem Arduino ist.

Das mit dem "unsigned long" kann ich ja ändern, ist aber vermutlich nicht die Ursache, weil genau diese UP's auch von dem Programmteil verwendet werden, mit dem die Motore schnell laufen, den ich aber durch das Abspecken weg gelassen habe.

vG

fredyxx

Mxt
28.08.2016, 17:26
Den Motoren ists auch völlig egal, wie der Code aussieht. Die laufen auch mit hässlichem. In deinem Falle nur halt langsam.

Nur wenn sich das jemand ansehen soll, ist das Aussehen nicht egal. Schon die Verwendung von Quote-Tags statt Code-Tags zeigt, dass das Aussehen egal ist.

HaWe
28.08.2016, 17:42
ich glaube, mxt will dir damit den versteckten Tipp geben, dass du doch bitte deinen Code in Code-Tags posten möchtest... ;)

ändere doch mal bitte dein float in uint32_t und teste es, und dann korrigiere und formatiere deinen Code anschließend um, und dann berichte, ob es mit uint32_t schneller läuft oder nicht 8)

Mxt
28.08.2016, 17:51
Ich sehe beim drüberschauen zumindest keine irgendwie blockierenden Konstrukte. Besonders effizient ist das goto Herumgehüpfe auf dem kleinen 8-Bit Prozessor sicher nicht. Kann er vielleicht nicht schneller ?

Ansonsten hätte ich die Zeilen

Schrittdauer = int(...
oder

if (dir == 0 && (micros() - ...
im Verdacht.

Float-Operationen auf 8-Bittern sind schnarchlangsam.

fredyxx
28.08.2016, 18:08
und formatiere deinen Code anschließend um

was heißt das?

- - - Aktualisiert - - -

Hallo,
>>>>>>>>>>>>>> eine große ENTSCHULDIGUNG, dass ich euch belässtigt habe <<<<<<<<<<<<<<<<<<<<<

Die Ursache ist total primitiv!

Ich habe in den Aufrufen von Mx_drive dauernd statt der Geschwindigkeit die Anzahl der Umdrehungen verändert und die Geschwindigkeit stand eben auf klein.

M1_drive(22, 24, 26, 28, M1_n, M1_v, M1_dir)

Ich denke, ich brauche mal eine Pause!!!!!

Trotzdem noch die Fragen:
was bedeutet uint32_t und
was ist damit gemeint: "Quote-Tags statt Code-Tags" ?

vG

fredyxx

Mxt
28.08.2016, 18:27
Siehst du, Computer machen immer genau das, was man sagt. Das ist das Problem beim Programmieren.

Zu uint32_t:

Typen wie int, long usw. sind auf unterschiedlichen Prozessoren unterschiedlich groß, haben also unterschiedlich viele Bits, z.B. int bei einem 8 Bit-Arduino 16 Bits, bei einem 32-Bit Arduino 32 Bit.

Darum gibt es in C und C++ Datentypen, die garantierte Größen haben.
http://en.cppreference.com/w/cpp/types/integer
Damit sind Programme besser auf andere Rechner übertragbar.

Tags:

Du zitierst deine Code
richtig wäre aber

auf "Erweitert" klicken und das # Symbol nehmen
Dann bleiben auch die Einrückungen stehen.

- - - Aktualisiert - - -

Ach ja, weiterhin macht eine Zeile wie

else if (dir == 1 && (micros() - M2_microsalt) > Schrittdauer) {
nicht das, was du glaubst.

Erstmal wird micros() - M2_microsalt berechnet. micros() liefert unsigned long, das wird in float umgewandelt und dann M2_microsalt abgezogen.

Dann muss Schrittdauer von unsigned int nach float umgewandelt werden, damit es verglichen werden kann.

Die ganze Zeile dauert wahrscheinlich etliche Mikrosekunden, weil der 8-Bit Prozessor die 32 Bit Werte nur in Häppchen verarbeiten kann.

fredyxx
28.08.2016, 18:42
Siehst du, Computer machen immer genau das, was man sagt. Das ist das Problem beim Programmieren.


Das musste ich auch schon von ca. 46 Jahren erfahren.




Ach ja, weiterhin macht eine Zeile wie

else if (dir == 1 && (micros() - M2_microsalt) > Schrittdauer) {
nicht das, was du glaubst.

Erstmal wird micros() - M2_microsalt berechnet. micros() liefert unsigned long, das wird in float umgewandelt und dann M2_microsalt abgezogen.

Dann muss Schrittdauer von unsigned int nach float umgewandelt werden, damit es verglichen werden kann.

Die ganze Zeile dauert wahrscheinlich etliche Mikrosekunden, weil der 8-Bit Prozessor die 32 Bit Werte nur in Häppchen verarbeiten kann.

Danke für den Tipp.
Wenn ich das richtig verstehe, sollte ich also M2_microsalt und Schrittdauer als unsigned long definieren?? Geht das dann schneller?

vG

fredyxx

HaWe
28.08.2016, 19:00
ja, liest du denn nicht was ich schreibe?
Natürlich musst du es in uint32_t ändern,
dann sollst du es testen,
und ob es dann schneller geht, wirst du sehen!
Wenn nicht, liegt es an was anderem, aber alle Zeit-Variablen (milles, micros) sind bei Arduino IMMER Integer-Werte!

Und dann formatiere bitte endlich deinen Code in Code-Tags um, man kann bei dem Durcheinander ja wirklich kaum was erkennen!

Peter(TOO)
28.08.2016, 20:10
Hallo fredyxx,

Das musste ich auch schon von ca. 46 Jahren erfahren.
1970? Was für einen Computer hast du da programmiert?

Grundsätzlich hat aber der Programmierspiel etwas mit Erfahrung zu tun und nur ganz wenig mit der verwendeten Sprache.
Insofern spielt es keine Rolle, dass dies dein erstes Projekt auf einem Arduino ist :-)


Wenn ich das richtig verstehe, sollte ich also M2_microsalt und Schrittdauer als unsigned long definieren?? Geht das dann schneller?
Früher konnten 8-Bit CPUs gerade mal zwei 8-Bit Werte addieren oder subtrahieren, grössere Werte musste man in einem Unterprogramm mit den 8-Bit Befehlen zusammensetzen.
Multiplikation und Division waren nur mit einem Unterprogramm möglich.
Später wurde dann auch die Multiplikation (8x8 Bit mit 16-Bit Resultat) und Division (16/8 Bit) als Befehl umgesetzt.
Heute können viele 8-Biter auch mit 16-Bit direkt rechnen.
Entsprechendes gilt für 16-Biter, nus das sie grundsätzlich mit 16-Bit am Stück rechnen könne und meistens auch teilweise mit 32-Bit

Floating Point (FP) ist da etwas komplizierter. Das einfache Format besteht aus 32-Bit welches aus Mantisse, Exponent und Vorzeichen zusammengesetzt ist. Das andere Standardformat hat 64-Bit und ein gebräuchliches internes Zwischenformat hat 80-Bit.
Bei den Grundrechenarten müssen Mantisse, Exponent und Vorzeichen getrennt verarbeitet und die Mantisse meist noch entsprechend geschoben (normalisiert) werden. Zuerst muss man die Teile aber auspacken.
Ergibt also eine Menge an Unterprogrammen.

Manche CPUs haben deshalb eine FPU, welche die FP-Operationen berechnet und meist auch noch ein paar Integer-Operationen beherrscht.
Der 8087, das war die zusätzlich FPU beim 8086, benötiget mehr Transistoren als der 8086, obwohl die ganze Speicher-Zugrifflogik vom 8086 ausgeführt wurde. Der 8086 bestand aus etwa 29'000 Transistoren, der 8087 aus etwa 40'000. Bei Intel ist die FPU erst seit dem 80386 mit auf dem CPU-Chip.
µC haben meistens keine FPU, da verwendet man die Transistoren lieber für die Peripherie.

FPU-Operationen benötigen meist ein paar Takte mehr als die entsprechenden Integer-Operationen.

Muss man die FPU per Software emulieren, ist man mindestens etwa 100x langsamer als die FPU.

Wenn man keine FPU hat, sollte man FP möglichst meiden, zudem kann man sich damit auch die ganze FP-Bibliothek sparen. OK, ist heute nicht mehr so wichtig, aber als man nur 4 oder 8 KByte ROM hatte, machten 1-2 KByte für die FP-Unterstützung einen grossen Unterschied.
Neben der eigentlichen FP-Bibliothek sind dann auch printf() und scanf() entsprechend grösser.

MfG Peter(TOO)

fredyxx
28.08.2016, 21:15
ja, liest du denn nicht was ich schreibe?


Lies bitte meinen Post von 19:08 Uhr. Da steht die Ursache.

vG

fredyxx

- - - Aktualisiert - - -


Hallo fredyxx,

1970? Was für einen Computer hast du da programmiert?

MfG Peter(TOO)

Wie der hieß, weiß ich nicht mehr, aber er füllte noch ganze Säle und die besseren nur noch große Schränke.

Danach kam sehr sporadisch verschiedenes andere.

Kannst du auf diese Frage nicht mit einem einfachen JA oder Nein antworten?

"Wenn ich das richtig verstehe, sollte ich also M2_microsalt und Schrittdauer als unsigned long definieren?? Geht das dann schneller?"

vG

fredyxx

Peter(TOO)
28.08.2016, 21:47
Hallo fredyxx,

Wie der hieß, weiß ich nicht mehr, aber er füllte noch ganze Säle und die besseren nur noch große Schränke.
Ab 1972 habe ich auf einem Wang 2200 gespielt.
Ab 1976 musste ich dann beruflich µP-Systeme entwickeln und programmieren.

"Wenn ich das richtig verstehe, sollte ich also M2_microsalt und Schrittdauer als unsigned long definieren?? Geht das dann schneller?"
Mit Integer werden die entsprechenden Rechenoperationen etwa 100x schneller.
Also ein paar µs anstatt ein paar 100µs.
Wie viel das auf dein ganzes Programm ausmacht, weiss ich so auch nicht.

MfG Peter(TOO)

fredyxx
28.08.2016, 22:16
Hallo fredyxx,

Mit Integer werden die entsprechenden Rechenoperationen etwa 100x schneller.

MfG Peter(TOO)

Hallo Peter,

zusammen mit dem Post von Mxt 19:27 ist mir nun nicht klar wie die Varablen M2_microsalt und Schrittdauer in so einem Befehl definiert sein sollten, damit er am schnellsten abgearbeitet wird.

Als int, float, unsigned long oder uint32_t?

"else if (dir == 1 && (micros() - M2_microsalt) > Schrittdauer) "

Bitte möglichst eine konkrete Antwort.

M2_microsalt als .....
Schrittdauer als .....

Die Ergebnisse von Schrittdauer liegen schon in einem Bereich von einigen 100 Mikrosekunden. Die Getriebe-Schrittmotore machen 4096 Schritte pro Umdrehung.

vG

fredyxx

Peter(TOO)
28.08.2016, 23:32
Hallo fredyxx,

zusammen mit dem Post von Mxt 19:27 ist mir nun nicht klar wie die Varablen M2_microsalt und Schrittdauer in so einem Befehl definiert sein sollten, damit er am schnellsten abgearbeitet wird.

Als int, float, unsigned long oder uint32_t?

"else if (dir == 1 && (micros() - M2_microsalt) > Schrittdauer) "

Bitte möglichst eine konkrete Antwort.

M2_microsalt als .....
Schrittdauer als .....

Die Ergebnisse von Schrittdauer liegen schon in einem Bereich von einigen 100 Mikrosekunden. Die Getriebe-Schrittmotore machen 4096 Schritte pro Umdrehung.
Möglichst klein ;-)

float und double sind PF-Werte, und können, ohne FPU, nur durch eine Bibliothek bearbeitet werden.

char, int und long hängen von der Implementierung, bzw. CPU ab. auf 8-Bitern ist int meistens 16-Bit lang und auf 16-Bitern 32-Bit.

K&R definierte mal:
Garantiert ist nur, dass char <= int <= long ist.
Ein char darf also auch 48-bit belegen.

Es gab/gibt auch CPUs mit anderen Wortbreiten z.B. 9, 12, 18, 36 und 48 Bit waren sehr verbreitet und entsprechend sind da die Bit-Breiten der C-Datentypen.

Weil es Programme gibt, welche nur bei bestimmten Bit-Breiten funktionieren, hat man die uintxx_t Typen eingeführt. Ein unsigned 8-Bit-Wert kann nur Werte zwischen 0...255, ein 16-Bit 0...65'335 und 32-Bit 0...4'294'967'295 annehmen. Grössere Werte führen zu einem Überlauf und falschen Ergebnissen!
uint8_t, uint16_t, uint32_t usw. haben, unabhängig von der Implementierung, garantierte Bit-Breiten.

Welche Variante die kleinste ist, welche du nehmen kannst, hängt also davon ab, welchen Wertebereich die Variable aufnehmen können muss.
Ich bin jetzt zu faul dies in deinem Programm nachzusehen.

Eine 8-Bit CPU kann einen 8-Bit Werte mit einem einzigen Maschinenbefehl verarbeiten, 16-Bit Operationen benötigen oft schon mehrere Befehle. Das hängt vom Befehlssatz der CPU ab und wie man 8-Bit CPU definiert!

Der Arduino MEGA hat einen ATmega1280 als CPU und diese kann nur 8-Bit direkt verarbeiten.


Die reale Welt ist halt nun nicht binär und lässt sich nicht mit Ja und Nein beantworten.

MfG Peter(TOO)

HaWe
29.08.2016, 08:13
millis() und micros() Funktionswerte sind in Arduino-C++ libs immer (!) als unsigned long definiert, stattdessen kann man auch uint32_t verwenden ( das ist auf dem Mega genau das gleiche, man erkennt diesen plattform-unabhängigen expliziten Datentyp nur besser beim Programmieren ). Wie mxt schon schrieb, ist float viel zu ungenau, und es führt höchstens zu Rechenfehlern und zu unnötigen Typecasting-Rechenoperationen. Aber intern wird doch bei millis() und micros() eh in 32bit Integer gerechnet, also warum abweichen? Das führt höchstens zu Rechenfehlern u/o zeitaufwändigen, unnötigen Umrechnungen.

Im Übrigen ist Arduino Sketch nicht C, sondern es benutzt C++, und das wäre ein ganz entscheidender Unterschied , wie einmal ein Arduino Entwickler schrieb (Paul Stoffregen, IIRC) denn es hat viele Eigenheiten, die nicht 100% C++ standard- und lib-kompatibel sind. Daher sollte man sich möglichst an die Arduino-Definitionen halten, wie sie in der Referenz veröffentlicht wurden (die aber auch manchmal fehlerhaft sind, wie in Github-Diskussionen nachzulesen ist).
Allgemeine C-Hinweise zu K+R oder gnu C oder was auch immer helfen bei Arduino Sketch also definitiv nicht weiter!

fredyxx
29.08.2016, 08:32
Ihr wisst sehr viel,

aber klarer wird es mir dadurch nicht.

Daher noch mal:

"else if (dir == 1 && (micros() - M2_microsalt) > Schrittdauer) "

Bitte möglichst eine konkrete Antwort.

M2_microsalt als .....
Schrittdauer als .....

die Schrittdauer, das habe ich vorher was falsche angegeben, hat eine Größenordnung von 400 us bis 20ms

vG

fredyxx

HaWe
29.08.2016, 08:42
ich schrieb doch ( mehrfach ):
millis() und micros() Funktionswerte sind in Arduino-C++ libs immer (!) als unsigned long definiert, stattdessen kann man auch uint32_t verwenden

also mach alles, was solche Werte zwischenspeichert und damit rechnet, ebenfalls zu unsigned long , stattdessen kann man auch hier uint32_t verwenden.

fredyxx
29.08.2016, 11:55
ich schrieb doch ( mehrfach ):

also mach alles, was solche Werte zwischenspeichert und damit rechnet, ebenfalls zu unsigned long , stattdessen kann man auch hier uint32_t verwenden.

Danke, das ist nun eindeutig.

Und noch mal herzlichen Dank für eure Geduld mit mir.

vG

fredyxx