PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Funktionsaufruf klappt nicht



fredyxx
04.06.2016, 23:52
Hallo,

in dem folgenden Programm, das noch nicht lauffähig ist, ist in Zeile 212 der Aufruf der Funktion "M2_drive", die sich ab Zeile 395 befindet.



/* Dieses Programm Version "M3 fahren für MEGA" steuert den Bagger ohne jegliche Sensoren.
* ********************Die Steppersoftware ist selber gemacht.*******************************
***** es sind die Programme
***** STOP und
***** Justierung (ohne Motor 1) und
***** Motor 2 fahren >>>> mit Schaufelbewegung
***** funktionsfähig

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

* ***********ab dieser Version wir JustPin erstmals anders verwendet. JustPin ist hier nur die Nummer des Eingangs,
der mit digitalRead gelesen werden soll ************

- 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 setup void loop UP Justierung UP Just_M2 UP Just_M3 UP Schaufel_Move
*/


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

SimpleTimer timer1; // Benennung der Timer



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 = false; // für UP Justierung
boolean M2solldrehen = true; // für UP Justierung
boolean M3solldrehen = false; // für UP Justierung
boolean Zeitaus1 = true; // Wird false, wenn Zeit von SimpleTimer 1 abgelaufen ist

float lzahn2_alt = 98.0; // Ausfahrlänge von Zahnstange 2 nach Justierung 98
float lzahn3_alt = 68.0; // Ausfahrlänge von Zahnstange 3 nach Justierung 68

int JustPin = 14; // mit digital Eingang 14 wird die jeweilige Motorbewegung gestoppt

int ENABLE_Pin = 40; // Freigabeausgang für Spindelstepper
int STEP_Pin = 50; // Frequenzausgang für Spindelstepper
int DIR_Pin = 52; // Richtungsausgang für Spindelstepper

int zeitId; // für den SimpleTimer

//++++++++++++++++++ für Stepper UPs
float M1_n = 1; // Wahl Umdrehungen, die der M1 machen soll
int M1_v = 18; // geht ohne Belastung noch bis 18 ; tatsächliche Geschwindigkeit aber ungenau
boolean M1_dir = 1; // gewünschte Richtung von M1; 1 gegen Uhrzeiger CCW, 0 mit Uhrzeiger CW

boolean M1_fertig = false;
boolean M1_Start = true;

float M2_n = 1; // Wahl Umdrehungen, die der M2 machen soll
int M2_v = 9; // geht ohne Belastung noch bis 18 ; tatsächliche Geschwindigkeit aber ungenau
boolean M2_dir = 0; // gewünschte Richtung von M2; 1 gegen Uhrzeiger CCW, 0 mit Uhrzeiger CW

boolean M2_fertig = false;
boolean M2_Start = true;
//++++++++++++++++++++++++++++++++++

void setup() {

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

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

pinMode (ENABLE_Pin, OUTPUT);
pinMode (STEP_Pin, OUTPUT);
pinMode (DIR_Pin, OUTPUT);

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);

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);

// Serial.print ( "in Just_M2");
// Serial.println ( "in Just_M2");

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

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


}

void loop() {



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


if (MK1_1 == LOW ) { //STOP
// hier keine Aktion
}
else if (MK1_2 == LOW && MK1_1 == HIGH ) { // Justierung
Justierung(); // Programm 2: Justierung
}
/* else if (MK1_3 == LOW && MK1_1 == HIGH ) { // M2 bewegen
M2_fahren(); // Programm 3: M2_fahren ; von der letzten Position auf maximal ausgefahren
}
else if (MK1_4 == LOW && MK1_1 == HIGH ) { // M3 bewegen
M3_fahren(); // Programm 4: M3_fahren ; von der letzten Position auf maximal ausgefahren
}
else if (MK1_5 == LOW && MK1_1 == HIGH ) { // x/y - Koordinate anfahren
xy_fahren(); // Programm 5: eine x/y -Koordinate anfahren
}
else if (MK1_6 == LOW && MK1_1 == HIGH ) { // "LKW" beladen
LKW_beladen(); // Programm 6: einen virtuellen LKW beladen
} */


timer1.run();




} //************* ENDE loop

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

void Justierung() {
static boolean Start_war = false;

if (Zeitaus1 == false) { // Zeitüberschreitung, Spindelschlitten stand in richtiger Position
M1solldrehen = true;
M2_fertig = false;
goto M2_Sprung; // Überspringt M1, weil JustPin 3 s LOW war.
}
// 11111111111111111111111
if (digitalRead (JustPin) == HIGH && M1solldrehen == false) {

Serial.print (" Start_war = ");
Serial.println (Start_war);
//delay(5000);

digitalWrite (ENABLE_Pin, LOW); // Freigabe Stepper einfahren
digitalWrite (DIR_Pin, HIGH); // Richtung einfahren
tone(STEP_Pin, 400, 1000) ; // (Pin, Frequenz, Dauer in ms)
Start_war = true;

}
// 2222222222222222222222222
else if (digitalRead (JustPin) == LOW && M1solldrehen == false) { // Motor 1 justieren
Serial.println (" 163 ");
Serial.println (Start_war);

// 2a2a2a2a2a2a2a2a2a2a2a2a
if (Start_war == false) { // Taster muss vor RESET betätigt sein, dann geht's hier weiter
zeitId = timer1.setInterval(1000, Zeitablauf1); // Endzeit und UP, wenn Endzeit erreicht ist
}
// 2b2b2b2b2b2b2b2b2b2b2b2b2b
else if (Start_war == true) { // Endposition erreicht
Serial.println (" 170 ");
//Serial.println (Start_war);

M1solldrehen = true;
M2solldrehen = false;
digitalWrite (ENABLE_Pin, HIGH); // Stepper STOP
Start_war = false;
timer1.disable(zeitId); // Timer1 löschen

}
}


M2_Sprung:

if (M2_fertig == false && Zeitaus1 == false) { //Motor 2 justieren
Serial.println (" M2_Sprung ");
// delay(5000);

M2_drive (22, 24, 26, 28, 0.5, 5, 0); // 22, 24, 26, 28
}

else if if ( digitalRead(JustPin) == LOW) { // bei LOW Motor STOP; LOW wegen internem PullUp-Widerstand {

M2_fertig = true; // stoppt den Motor
lzahn2_alt = 98.0;

}


if (stepper_M3.isDone() && M3solldrehen == false && M2solldrehen == true && (JustM3var || digitalRead (JustPin) == HIGH )) { // && (Just_M3() || digitalRead (JustPin) == HIGH )

Just_M3();
}



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


/************************ UP Just_M2 ***********************************/



/************************ UP Just_M3 ***********************************/

/*void Just_M3() {

// setRPM() und setSPR werden hier nicht gebraucht, weil optional und dann die Default-Werte der Library übernommen werden
// diese sind 4075.7728395, 12, CW und byte[]){8, B1000, B1100, B0100, B0110, B0010, B0011, B0001, B1001}


stepper_M2.setDirection(STOP);
stepper_M2.rotateDegrees(5);
stepper_M3.setDirection(CCW);
stepper_M3.rotateDegrees(5);

JustM3var = digitalRead(JustPin); // muss 1 x gesetzt werden, denn wenn dann JustPin LOW wird, käme das Programm nicht wieder bis hier her.

if ( digitalRead(JustPin) == LOW) { // bei LOW Motor STOP; LOW wegen internem PullUp-Widerstand

M3solldrehen = true; // stoppt den Motor
lzahn3_alt = 68.0;

}
} // ************************ Ende UP Just_M3 */




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

Zeitaus1 = false; //

Serial.println (" 258 ");


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







// >>>>>>>>>>>>>>>>>>>>> hier Schaufel bewegen >>>>>>>>>>>>>>>>>>>>>>>>>>>>



if ( stepper_M2.isDone() == true && M1_Zeit == 0 && M1_fertig == false ) { // mit true ist der erste Auftrag an M2 erledigt,
//-------------------------------------------------------------- M1_fertig ist da, damit M1_Zeit nur einmal erfasst wird
M1_Zeit = millis();
digitalWrite (ENABLE_Pin, LOW); // Freigabe M1-Treiber
// M2solldrehen = false; // bevor der Zweite aktiv wird,soll aber die Schaufel bewegt werden

Serial.print ( "M1_Zeit = ");
Serial.println ( M1_Zeit);

Schaufel_Move ( 800, 3500, HIGH); // Frequenz ; Laufzeit in ms ; Drehrichtung, HIGH = ausfahren
//----------------------------------------- die Werte entsprechen einem Spindelweg von 54 mm
}

if (stepper_M2.isDone() == true && (millis() - M1_Zeit) > 3500 && M1_fertig == false) {

Schaufel_Move ( 800, 3500, LOW); // Frequenz ; Laufzeit in ms ; Drehrichtung, HIGH = ausfahren

if ((millis() - M1_Zeit) > 7000) { // erst nach 7 s ist der Vorgang von M1 abgeschlossen

M1_fertig = true;
digitalWrite (ENABLE_Pin, HIGH); // Freigabe M1-Treiber

}

}
// Serial.print ( "stepper_M2.isDone() = ");
// Serial.println ( stepper_M2.isDone());

if (stepper_M2.isDone() == true && M2_zurueck == true && M1_fertig == true) { // isDone erst dann true, wenn 1. Auftrag für M2 erledigt.

stepper_M2.setDirection(CW); // es müssen wohl die Parameter für beide Motore gleichzeitig eingegeben werden, sonst keine Funktion!!??
stepper_M2.rotateDegrees(Drehwinkel_M2);
stepper_M3.setDirection(STOP); // Motor dreht nicht
stepper_M3.rotateDegrees(5); // aber dieser Parameter muss trotzdem sein.

M2_zurueck = false;



}

} // ************************ Ende UP M2_fahren




// >>>>>>>>>>>>>>>>>>>>> hier Schaufel bewegen >>>>>>>>>>>>>>>>>>>>>>>>>>>>




if ( stepper_M3.isDone() == true && M1_Zeit == 0 && M1_fertig == false ) { // mit true ist der erste Auftrag an M2 erledigt,
//-------------------------------------------------------------- M1_fertig ist da, damit M1_Zeit nur einmal erfasst wird
M1_Zeit = millis();
digitalWrite (ENABLE_Pin, LOW); // Freigabe M1-Treiber
// M2solldrehen = false; // bevor der Zweite aktiv wird,soll aber die Schaufel bewegt werden



Schaufel_Move ( 800, 3500, HIGH); // Frequenz ; Laufzeit in ms ; Drehrichtung, HIGH = ausfahren
//----------------------------------------- die Werte entsprechen einem Spindelweg von 54 mm
}

if (stepper_M3.isDone() == true && (millis() - M1_Zeit) > 3500 && M1_fertig == false) {

Schaufel_Move ( 800, 3500, LOW); // Frequenz ; Laufzeit in ms ; Drehrichtung, HIGH = ausfahren

if ((millis() - M1_Zeit) > 7000) { // erst nach 7 s ist der Vorgang von M1 abgeschlossen

M1_fertig = true;
digitalWrite (ENABLE_Pin, HIGH); // Freigabe M1-Treiber

}

}
// Serial.print ( "stepper_M2.isDone() = ");
// Serial.println ( stepper_M2.isDone());

if (stepper_M3.isDone() == true && M3_zurueck == true && M1_fertig == true) { // isDone erst dann true, wenn 1. Auftrag für M2 erledigt.

stepper_M3.setDirection(CCW); // es müssen wohl die Parameter für beide Motore gleichzeitig eingegeben werden, sonst keine Funktion!!??
stepper_M3.rotateDegrees(Drehwinkel_M3);
stepper_M2.setDirection(STOP); // Motor dreht nicht
stepper_M2.rotateDegrees(5); // aber dieser Parameter muss trotzdem sein.

M3_zurueck = false;



}

} // ************************ Ende UP M3_fahren



//***************************************UP Schaufel_Move ****************************

void Schaufel_Move (int Frequenz, int Laufzeit , boolean DrehRicht) {

// Start = LOW; // wenn Motor nur einmal laufen soll

digitalWrite (DIR_Pin, DrehRicht);
tone(STEP_Pin, 800, Laufzeit) ;

}
//************************* ENDE UP Schaufel_Move




// ***************************** 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;


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 vom Hauptprogramm 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



In Zeile 212 erhalte ich die Fehlermeldung:
"'M2_drive' was not declared in this scope"

Was ist da falsch? in einem anderen Programm hat das so funktioniert.

Gruß

fredyxx

witkatz
05.06.2016, 01:20
In Zeile 212 erhalte ich die Fehlermeldung:
"'M2_drive' was not declared in this scope"In Zeile 212 kennt der Compiler die Funktion noch nicht. Ein Funktionsprototyp (https://de.wikipedia.org/wiki/Funktionsprototyp) vor der main, also irgendwo oben bei den ganzen globalen Deklarationen sollte helfen
void M2_drive (int p1, int p2, int p3, int p4, float n, int v, boolean dir);

fredyxx
05.06.2016, 06:12
Danke,
diese Fehlermeldung ist nun weg.

Merkwürdig finde ich es trotzdem. In dem anderen Programm, in dem das ohne Funktionsprototyp funktioniert, ist der Aufruf in 66 und die Funktion in 288.
Spielt da die Größe des Programms eine Rolle?

Gruß
fredyxx

Rabenauge
05.06.2016, 12:08
Nö.
Es kommt auf die Reihenfolge an, in der der Compiler das Programm abarbeitet (bzw. überprüft, zu dem Zeitpunkt tut er noch gar nicht mehr).
Das ist dann, aus Programmierersicht, mehr oder weniger Glückssache.
Also sowas immer schön in den Header, dann passt das auch.

fredyxx
05.06.2016, 18:07
Nö.

Also sowas immer schön in den Header, dann passt das auch.

Was in den Header? Die Funktionen oder den Funktionsprototyp? Vor Setup oder vor loop?

Gruß
fedyxx

021aet04
05.06.2016, 19:33
Header sind die Dateien mit der Endung ".h". Dort stehen genau solche Dinge drinnen. In der Header Datei steht z.b. Drinnen

void delay(void)
Und in der zugehörigen C-Datei was damit gemacht werden soll. Z.b.

Void delay(void)
{
Asm volatile ("nop");
}

In der Header stehen aber auch die ganzen defines drinnen. Öffne einmal eine Header und schau nach was da alles drinnen steht.

MfG hannes

fredyxx
05.06.2016, 20:04
Hallo,

das ist für mich unverständlich, da ich die Arduino IDE nutze und da taucht (außer " #include <SimpleTimer.h>" ) weder in meinem Programm noch in dem Ordner, in dem mein Programm liegt, etwas mit .h auf.

Gruß

fredyxx

021aet04
05.06.2016, 20:47
Es sind bestimmt mehr Header Dateien eingebunden. Es gibt Header Dateien die durch andere Headerdateien eingebunden sind. Außerdem werden Standart Header Dateien von der IDE selbstständig eingebunden. Ich kenne die Arduino IDE nicht aber beim AVR Studio kann man die eingebundenen Header Dateien sehen.

MfG Hannes

HaWe
05.06.2016, 21:10
@ fredyxx:

die Arduino IDE bindet mehr Headerdateien ein (automatisch, im Hintergrund) als man jemals sieht oder sehen wird.
Sie erstellt sogar meistens selbstständig Templates der programmierten Funktionen und setzt sie selbstständig ganz oben im Code (temporär) ein, ohne dass man es sieht, und compiliert und linkt dann alles.

100%ig sicher klappt das aber nicht immer, und dann musst du von Funktionen, die unterhalb einer aufrufenden Funktion stehen, selber das Template erstellen uns es oberhalb der aufrufenden Funktion einfügen.

Das ist genau das, was daher in deinem Falle auch von Hand gemacht werden musste, und der Grund, warum es dann hinterher funktioniert hat.

Rabenauge
06.06.2016, 21:12
Nee-einfach VOR setup() meinte ich.

Erfahrungsgemäss wird alles, was dort steht, "global" verfügbar, auch wenn man mehrere Tabs benutzt (die üm übrigen auch jeder ne eigene Datei werden).