Go Down

Topic: Projekt: Schrittmotor (Read 13319 times) previous topic - next topic

sonyfuchs

Ja, ohne GUI wärs erstmal schon praktischer.
Hab die Rampen ein bischen anders gestaltet, direkt unten wo clkState high und low gestellt wird. Finde ich simpler:
Code: [Select]
const int CLK =24; //Schrittgeschwindigkeit
const int DIR =25; //Drehrichtung
const int NEN =22; //NOT ENABLE
const int HAL =23; //Halbschritt
int  CLKstate = LOW; //Zwischenspeicher für Taktzustand
long previousMicros = 0; //Letztes Timerupdate
long interval = 2000;  //Zeit zwischen zwei Schritten
char BET;      // Betrieb
char RIC;      // Richtung
char HSC;      // Halbschritt
int  ANZ;      // Anzahl Schritte
char eingabe[8]; //Die eingegeben Zeichen
int gradt = 0;  // Tausenderstelle
int gradh = 0;  // Hunderterstelle
int gradz = 0;  // Zehnerstelle
int grade = 0;  // Einerstelle
int grad = 0;   // bewegung in Grad
double gradD = 0; // Gradangabe Dezimal
 
void setup()
{
  pinMode(CLK, OUTPUT);
  pinMode(DIR, OUTPUT);
  pinMode(NEN, OUTPUT);
  pinMode(HAL, OUTPUT);
  digitalWrite(NEN, HIGH);
  Serial.begin(9600);   
  Serial.println("ABC D , A: an/aus, B: links/rechts, C: halbschritt/vollschritt, D: Schritte(4 stellig)");
}

void loop()
{
  unsigned long currentMicros = micros(); // Variable die vom Timer hochgezählt wird
  if (Serial.available() >= 8)           // warten bis zwei Zeichen eingegeben wurden
  {
    for(int i = 0; i < 8 ; i++)
    eingabe[i] = Serial.read();

    BET = eingabe[0];
    RIC = eingabe[1];
    HSC = eingabe[2];
   
    gradt = eingabe[4];
    gradh = eingabe[5];
    gradz = eingabe[6];
    grade = eingabe[7];
   
    grad = (gradt-48)*1000+(gradh-48)*100 + (gradz-48)*10 + (grade-48);
    gradD = (double)grad / 360.0 * 192.0;
    ANZ = (int)gradD;
   
    for ( int i = 0; i < 7 ; i++)             //Ausgabe Anfang
     {
      Serial.print("Eingabe[");
      Serial.print(i);
      Serial.print("]: ");
      Serial.print(eingabe[i]);
      Serial.print("  -  ");
     }
    Serial.print("Eingabe[7]: ");
    Serial.println(eingabe[7]);
     
    Serial.print("Betrieb: ");               
    Serial.print(BET);                       
    Serial.print(" - Richtung: ");           
    Serial.print(RIC);
    Serial.print(" - Halbschritt: ");
    Serial.print(HSC);
    Serial.print(" - Schritte: ");
    Serial.println(ANZ);                      //Ausgabe Ende
 
    if (BET == '0')                 //AUS
      digitalWrite(NEN, HIGH);
    else if (BET == '1')            //AN
      digitalWrite(NEN, LOW);
    if (RIC == '0')                 //im Uhrzeigersinn
      digitalWrite(DIR, LOW);     
    else if (RIC == '1')            //gegen Uhrzeigersinn
      digitalWrite(DIR, HIGH);
    if (HSC == '0')                 //ohne Halbschritt
      digitalWrite(HAL, LOW);       
    else if (HSC == '1')            //mit Halbschritt
      digitalWrite(HAL, HIGH);
     
    Serial.print("NEN: ");              //Testen der Verrieglung
    Serial.println(digitalRead(NEN));   //später rausnehmen!!!
  }
 
  if (currentMicros- previousMicros > interval && BET == '1' && ANZ > 0 && ANZ <9999) //Takt
  {
    previousMicros = currentMicros;
    if (CLKstate == LOW)
      CLKstate = HIGH;
    else
      CLKstate = LOW;
    digitalWrite(CLK, CLKstate);
      ANZ--;
    if (interval > 1500 && ANZ > gradD *2 /3)  //Startrampe
      interval--;
    else if (interval < 2000 && ANZ < gradD /3)  //Endrampe
      interval++;
    if(HSC == '0')
      ANZ--;
  }
  else if ( ANZ <= 0 )
  {
    BET = '0';
    digitalWrite(NEN, HIGH);
    interval=2000;
  }
 
}


Jetzt fehlt nur noch die korekte Eingabe.
Wenn jemand was konkretes hat, wäre ich sehr dankbar.

sonyfuchs

So, die Eingabe steht. Kann mir jemand erklären warum ich die Variablen "interval" nicht als array anlegen kann?

Ich hab mal das Programm angehängt, da es sonst die erlaubten Zeichen pro Beitrag überschreitet.

Lieben Gruß

Serenifly

Was meinst du damit, dass du es nicht kannst? Was kommt da als Fehler?

Sollte eigentlich so gehen:
long interval[] = { 2000, 2000, 3000, 4000, 3000, 3000 };

sonyfuchs

Das hätte ich vielleicht beischreiben müssen. Das Programm lässt sich mit dem intervall Array fehlerfrei kompilieren, aber die Motoren brumen und bewegen sich nicht.

sonyfuchs

Und noch ne Frage, wenn ich "long interval[6];" schreibe, hab ich dann 6 oder 7 Variablen? Also interval[0]-interval[5] oder interval[0]-interval[6] oder interval[1]-interval[6]?

Serenifly

#35
Oct 28, 2013, 08:28 pm Last Edit: Oct 28, 2013, 08:44 pm by Serenifly Reason: 1
Arrays fangen in den meisten Sprachen bei 0 an. "variable[6]" sind 6 Variablen mit den Indices 0 bis 5. Aus der Computer-Steinzeit gibt es viele Sprachen die mit 1 fangen, z.B. Fortran. Pascal und Lua sind seltene Ausnahme was moderne Sprachen betrifft (und in Pascal hat man sogar freie Wahl was die Indices betrifft).

Vor allem beim schreibenden Zugriff musst du da in C/C++ aufpassen, dass du nicht über die Grenzen schreibst. Anders als bei "managed" Sprachen mit VM wie Java oder C# wird da nirgends geprüft ob die Indices gültig sind. Du überschreibst dann einfach Speicher anderer Variablen, oder noch schlimmer Sprungadressen.

uwefed

Achtung:
Der Compiler läßt ohne Murren array[6] oder array[7] oder array[325]  bei einem Array[6] zu. Du schreibst dann aber außerhalb des für das Array reservierten Speicherbereichs und somit auf andere Variablen, Systemvariablen, STACK ecc. So bringt man effektiv ein Sketch zu aus unerfindlichen Gründen Absturz bzw zu den unerwartetsten Fehlfunktionen.

Grüße Uwe

sonyfuchs

Aha, vielen Dank. Es läuft jetzt. Ich habe einfach am Anfang, also noch vor setup() geschrieben
Code: [Select]
int       interval[7] = { 0, 3000, 3000, 3000, 3000, 3000, 3000}; //Zeit zwischen zwei Schritten
das funktioniert.
schreib ich aber wie ursprünglich vor setup():
Code: [Select]
int       interval[7] ; //Zeit zwischen zwei Schritten
und lasse das Array dann im setup() mit einer for Schleife beschreiben, bewegt sich der Motor nicht.
Es ist jetzt zwar gut, ich würde aber dennoch gerne verstehen wo der Unterschied in den beiden Methoden ist.
Ich meine setup() wird doch einmalig ausgeführt bevor das eigentliche Programm startet.

michael_x

Quote
... lasse das Array dann im setup() mit einer for Schleife beschreiben, bewegt sich der Motor nicht.
Es ist jetzt zwar gut, ich würde aber dennoch gerne verstehen wo der Unterschied in den beiden Methoden ist.


Meine frisch polierte Kristallkugel sagt mir, dass du vermutlich in setup()  noch mal eine lokale Variable
Code: [Select]
int interval[];
definiert hast. Aber eventuell kannst du uns ja einen noch blöderen Fehler zeigen ;)
Generell hast du recht: Es sollte für loop() ziemlich egal sein, ob der RAM -Bereich namens interval in setup() oder kurz vorher beschrieben wurde.


Debuggen geht bei Arduinos mit Serial.print();

sonyfuchs

Nö hab ich nicht. Ich hab mal im Anhang das aktuelle Programm, wies funktioniert.
Tu ich jetzt in Zeile 47 die Zeile vor dem "=" beenden und statdessen in Zeile 100 interval, wie die anderen Variablen auch, einfach mit Werten beschreiben, laufen die Motoren nicht.

Serenifly


Code: [Select]
int       interval[7] = { 0, 3000, 3000, 3000, 3000, 3000, 3000}; //Zeit zwischen zwei Schritten

Kleine Feinheit: Wenn du ein Array so gleich initialisierst, brauchst die Größenangabe in Klammern nicht unbedingt. Das kann der Compiler selbst herausfinden. Lediglich bei zwei-dimensionalen Arrays muss eine Dimension angegeben werden.

Schadet aber natürlich nicht. Gerade wenn man die Initialisierung auskommentieren will. :)


Aber generell musst du globale Variablen (die außerhalb der Methoden am Anfang stehen) nicht per Hand mit 0 beschreiben. Globale Variablen werden auf einen Default-Wert initialisiert - der in allen Fällen 0 sein dürfte. Lediglich lokale Variablen (innerhalb von Methoden) haben den Wert der zufällig im Speicher steht.

sonyfuchs

@Serenifly : Gilt das auch für Array? Wenn ich in der Zeile:
Code: [Select]
int       interval[7] = { 0, 2000, 2500, 3000, 3000, 3000, 3000}; //Zeit zwischen zwei Schritten
die Null weglasse, sagt er:
error: expected primary-expression before ',' token

@all:
hier ist noch so ein Ding, das ich nicht verstehe:
Wenn ich die Zeile 425 vor dem = beende und dafür die 4 Zeilen darunter benutze bewegen sich die Motoren nicht. Es gibt aber keinen Fehler beim kompilieren

michael_x


Debuggen geht bei Arduinos mit Serial.print();

Wenn du mehrmals micros() aufrufst, werden die eventuell unterschiedliche Werte liefern.
Die Reihenfolge, in der micros() bei
Code: [Select]
    long currentMicros[7] = {micros(), micros(), micros(), micros(), micros(), micros(), micros()};
ausgeführt wird, würde mich interessieren.

Ausserdem liefert micros() unsigned long, nicht long.

Wofür das so gut sein soll, wäre eine andere Frage ;)

sonyfuchs

Naja, ich lass das erstmal so wie es ist.
Mal zu was anderem, wie berechne ich die Zeit, die ein Motor braucht um eine bestimmte Anzahl Schritte auszuführen.
Meine PTP Synchronisation stimmt noch nicht, da ich darin die nicht linearen Rampen nicht berücksichtige.

Serenifly


error: expected primary-expression before ',' token

Dann hast du das geschrieben:
int interval[7] = { , 2000, 2500, 3000, 3000, 3000, 3000};

Das geht natürlich nicht. Was ich meinte, ist dass die 7 weglassen kannst.

Go Up