Go Down

Topic: Selektiermaschine bauen (Read 2575 times) previous topic - next topic

agmue

Warum sollte eine Position ausgerechnet in Grad ausgedrückt werden, und nicht in Steps? Eine einmalige Umrechnung der relevanten Positionen in Steps reicht doch völlig aus?
Ich habe von diesem Projekt eine gewisse Vorstellung, die natürlich gänzlich falsch sein kann. Was er genau vorhat, weiß nur der TO, wenn er es denn weiß ;)

Ich stelle mir eine in gleiche Segmente eingeteilte Scheibe vor, die nach bestimmten Kriterien Segment für Segment immer in die selbe Richtung gedreht wird. Bei beispielsweise 10 Segmenten entfallen auf jedes Segment 360 / 10 = 36 Grad oder (ohne Getriebe) 200 / 10 = 20 Schritte. Nach zehn Segmentbewegungen steht die Scheibe wieder an der selben Stelle, wie am Anfang. Das Spiel kann von Neuem beginnen.

Wenn es für das Projekt relevant sein sollte, daß die Scheibe immer wieder zur Anfangsposition zurückkehrt, so wäre das ohne Getriebe gegeben.

Mit Getriebe haben wir (5 + 2/11) * 200 = 1036,36 Vollschritte für eine Umdrehung (der Unterstrich ist ein Überstrich). Mal abgesehen davon, daß sich diese Zahl nur zu einer krummen Zahl je Segment teilen läßt, steht nach 1036 Schritten die Scheibe also knapp neben der Anfangsposition. Gehen wir mal davon aus, diese geringe Abweichung ist für dieses Projekt nicht wichtig. Nach 11 Umdrehungen addiert sich die Abweichung aber zu einem ganzen Vollschritt, was eine Korrektur möglich macht. Wenn man nach 11 Umdrehungen einfach einen Schritt weiterdreht, erreicht die Scheibe wieder die Anfangsposition.

Auf diesen Sachverhalt wollte ich hingewiesen haben.
Wahnsinn und Verstand trennt nur eine dünne Wand. (Daniel Düsentrieb)

postmaster-ino

Hi

Wenn wir in JEDER Runde aber ein Ref-Signal bekommen, können wir dort die Schritte Nullen - und ab Null sind Es 513 Schritte bis Position 3, 23 Schritte später ist Position 2, 55 Schritte danach kommt 3 und weitere 200 Position 4.
Nun drehen wir entweder unsere berechneten Schritte weiter, bis wir wieder bei Position Null sind, oder warten, bis der REF-Taster meint, wir wären da.

Das meinte ich mit Komma-Grad.

Nach jeder Umdrehung bekommen wir unser Ref - ob wir dann in Grad einen Step zu weit links stehen, oder zu weit rechts - sind Abweichungen hinter dem Komma.

Klar, wenn wir hiermit zwölf Runden a 1000 Steps drehen wollen, aber pro Runde 3,6% Fehler machen, werden wir nicht wieder 'vorne' ankommen.
Aber: Wir bekommen ja unseren Ref - und damit sind sämtliche Ungenauigkeiten vom Tisch - zumindest Die, Die sich unangenehm auswirken würden - und die Anderen sind eh wurscht.

MfG
anscheinend ist Es nicht erwünscht, einen Foren-internen Link als 'Homepage' einzubinden, damit JEDER nur einen Klick von combie's Liste zum Thema State-Maschine entfernt ist.
... dann eben nicht ...

DrDiettrich

@agmue: Dein Vertrauen in die Positioniergenauigkeit der Mechanik möchte ich haben :-]

Wieviel Grad Spiel hat denn der Drehteller+Getriebe+Motor?

hajos118

Also in industriellen Anlagen wird für jede Sollposition ein Sensorsignal erwartet.
Einmaliger mechanischer Aufwand, aber keine Probleme in der Software.
Lösung: Sensor (Reflexlichtschranke) mit engem "Blickwinkel" an der Referenzstelle, Markierungen am Umfang des Drehtellers.
Orthographie und Interpunktion folgen keiner gültigen Norm. Wer Fehler findet darf sie behalten!

4711

Jungs, brauche eure Hilfe  :o
Code: [Select]
// GLOBALE KONSTANTEN ---------------------------------
  const unsigned int iStepsGoodCase = 350; // Steps zum Auswurf guter Hülsen
  const bool iDirectionGoodCase = LOW; // Richtung für die Drehbewegung
  const unsigned int iStepsBadCase = 200; // Steps zum Auswurf falscher Hülsen
  const bool iDirBadCase = HIGH; // Richtung für die Drehbewegung
  const unsigned int iStepsOfRefSwitchUp = 1000; // Steps zum Auffahren des Referenzschalter
  const unsigned int iStepsOfRefSwitchDown = 100; // Steps zum Abfahren des Referenzschalter
  const unsigned int iSpeedRefUp = 200; // Speed zum Auffahren des Refschalter
  const unsigned int iAccRefUp = 200; // Dynamik zum Auffahren des Refschalter
  const unsigned int iSpeedRefDown = 50; // Speed zum Auffahren des Refschalter
  const unsigned int iAccRefDown = 50; // Dynamik zum Auffahren des Refschalter
  const unsigned int iFaultTime = 5000; // Fehlerzeit [ms]
  const unsigned int iDelayTime = 50; // Verzögerungszeit
// GLOBALE I/O
  const unsigned int I_Sensor1 = 3; // Eingang vom Sensor 1 = Erkennung der Hülse
  const unsigned int I_Sensor2 = 4; // Eingang vom Sensor 2 = korrekte Höhe
  const unsigned int I_Sensor3 = 5; // Eingang vom Sensor 3 = falsche Höhe
  const unsigned int I_PosSensorEmptyBadCase = 6; // Position Auswurf falscher Hülsen
  const unsigned int I_PosSensorInputCase = 7; // Position Einwurf neuer Hülsen
  const unsigned int I_PosSensorCheckGoodCase = 8; // Position Überprüfung ZH
  const unsigned int I_PosSensorEmptyGoodCase = 9; // Position Auswurf guter Hülsen
  const unsigned int O_StepperENA = 11; // Enable Signal zum Treiber
  const unsigned int O_StepperDIR = 12; // Direction Signal zum Treiber
  const unsigned int O_StepperPUL = 13; // Puls Signal zum Treiber
// GLOBALE MERKER -------------------------------------      
  bool bRefMerker = LOW; // Merker ob referenziert wurde
  bool bSensor1 = LOW; // Merker für Sensorsignal
  bool bSensor2 = LOW; // Merker für Sensorsignal
  bool bSensor3 = LOW; // Merker für Sensorsignal
  bool bPosSensorEmptyBadCase = LOW; // Merker für Sensorsingal
  bool bPosSensorInputCase = LOW; // Merker für Sensorsingal
  bool bPosSensorCheckGoodCase = LOW; // Merker für Sensorsingal
  bool bPosSensorEmptyGoodCase = LOW; // Merker für Sensorsingal
  bool bError = LOW; // Merker für Fehlerausgabe
  unsigned int iRefState = 0; // Schrittindikator
  unsigned int iError = 0; // Error
  unsigned long liErrorTime = 0; // Startzeit für Zeitabfragen
// DEBOUNCE ------------------------------------------
  unsigned long lastDebounceTime = 0;  // the last time the output pin was toggled
  unsigned long debounceDelay = 50;    // the debounce time; increase if the output flickers
  unsigned int iSensor1State;          // aktueller Zustand vom Eingang
  unsigned int ilastSensor1State = LOW; // letzter Zustand vom Eingang
// Bibliotheken --------------------------------------.
  #include <AccelStepper.h>
  AccelStepper stepper(AccelStepper::DRIVER,O_StepperPUL,O_StepperDIR);
// ----------------------------------------------------
// INIT -----------------------------------------------
// ----------------------------------------------------
 void setup() {
  // Define I/O
  pinMode (I_Sensor1, INPUT_PULLUP);
  pinMode (I_Sensor2, INPUT_PULLUP);
  pinMode (I_Sensor3, INPUT_PULLUP);
  pinMode (I_PosSensorEmptyBadCase, INPUT_PULLUP);
  pinMode (I_PosSensorInputCase, INPUT_PULLUP);
  pinMode (I_PosSensorCheckGoodCase, INPUT_PULLUP);
  pinMode (I_PosSensorEmptyGoodCase, INPUT_PULLUP);
  pinMode (O_StepperENA, OUTPUT);
  pinMode (O_StepperDIR, OUTPUT);
  pinMode (O_StepperPUL, OUTPUT);
  // Define Serial Output to display machine status
  Serial.begin (9600); // Datenrate 9600 bps
}
void Debounce() {
  int ireadingSensor1 = digitalRead(I_Sensor1);
  if (ireadingSensor1 != ilastSensor1State) {
    lastDebounceTime = millis();
  }
  if ((millis() - lastDebounceTime) > debounceDelay) {
    if (ireadingSensor1 != iSensor1State) {
      bSensor1 = ireadingSensor1;
      if (iSensor1State == HIGH) {
        bSensor1 = !bSensor1;
      }
    }
  }
  ilastSensor1State = ireadingSensor1;
}
// ----------------------------------------------------
// CODE - REF -----------------------------------------
// ----------------------------------------------------
void Referenz() // Refschalter = bPosSensorEmptyBadCase
{ switch (iRefState) {
    // ------------------------------------------------
    case 0: // ist der Selektierarm leer ?
      Serial.println("Referenz Start --------------");
      if (bSensor1 == LOW)
       { iRefState = 1;
         Serial.println("R0/ Selektorarm ist leer -> R1");
       }
      else
       { iError = 1000;
       } break;
    // ------------------------------------------------
    case 1: // Entscheidung ob der Ref-Sensor belegt ist
      if (bPosSensorEmptyBadCase == LOW)
       { iRefState = 2;
         Serial.println("R1/ CalSensor ist LOW -> R2");
       }
      else if (bPosSensorEmptyBadCase == HIGH)
       { iRefState = 10;
         Serial.println("R1/ CalSensor ist HIGH -> R10");
       }
      else
       { iError = 1001;
       } break;
    // ------------------------------------------------
    case 2: // Richtung Refschalter fahren
      stepper.setAcceleration (iAccRefUp);
      stepper.setSpeed (iSpeedRefUp);
      stepper.setMaxSpeed (1000);
      digitalWrite(O_StepperENA,HIGH);
 //     digitalWrite(O_StepperDIR,HIGH);
      stepper.move (iStepsOfRefSwitchUp);
    stepper.runToNewPosition(0);
    stepper.runToNewPosition(5000);
 /*   stepper.runToNewPosition(10);
    stepper.runToNewPosition(1200);
*/
      iRefState = 3;
      liErrorTime = millis();
      Serial.println("R2/ Move to PosEmptyBadCase started -> R3");
      break;
    // ------------------------------------------------
    case 3: // am Refschalter angekommen ?
      if (bPosSensorEmptyBadCase == HIGH)
      { stepper.stop ();
        iRefState = 10;
        Serial.println("R3/ PosSensorBadCase aktiviert, Move Stop -> R10");
        delay(iDelayTime);
      }
      else if ((millis() - liErrorTime) > iFaultTime)
      { stepper.stop ();
        iError = 1003;
      } break;
    // ------------------------------------------------
    case 10: // vom Refschalter langsam runterfahren
      stepper.setAcceleration (iAccRefDown);
      stepper.setSpeed (iSpeedRefDown);
      digitalWrite(O_StepperENA,HIGH);
      stepper.move (iStepsOfRefSwitchDown);
      iRefState = 11;
      liErrorTime = millis();
      break;
    // ------------------------------------------------
    case 11: // vom Schalter herunten?
      if (digitalRead (I_PosSensorEmptyBadCase) == LOW)
      { stepper.stop ();
        stepper.setCurrentPosition (0);
        iRefState = 12;
        delay(iDelayTime);
      }
      else if ((millis() - liErrorTime) > iFaultTime)
      { stepper.stop ();
        iError = 1011;
      } break;
    // ------------------------------------------------
    case 12: // Finish
      bRefMerker == HIGH;
      Serial.println("R12/ RefMerker HIGH");
      Serial.println("R12/ Referenz ENDE ----------");
      break;
    // ------------------------------------------------
    default:
      iError = 1099;
      break;
    // ------------------------------------------------
  }
}
// ----------------------------------------------------
// MAIN - CODE ----------------------------------------
// ----------------------------------------------------
void loop()
{ // Local Merker -------------------------------------
  // poll Inputs --------------------------------------
//    Debounce();
    bSensor1 = digitalRead (I_Sensor1);
    bSensor2 = digitalRead (I_Sensor2);
    bSensor3 = digitalRead (I_Sensor3);
    bPosSensorEmptyBadCase = digitalRead (I_PosSensorEmptyBadCase);
    bPosSensorInputCase = digitalRead (I_PosSensorInputCase);
    bPosSensorCheckGoodCase = digitalRead (I_PosSensorCheckGoodCase);
    bPosSensorEmptyGoodCase = digitalRead (I_PosSensorEmptyGoodCase);
  // --------------------------------------------------
  // REF ----------------------------------------------
  // --------------------------------------------------
    if (!bRefMerker && iError == 0)
     { Referenz(); }
}


void Referenz() case 2
stepper.move löst keine Bewegung aus?
stepper.runToNewPosition blockiert den Ablauf?

Sorry, steh am Schlauch was das Problem ist, dachte accelstepper blockiert niemals den Sketch?

Tommy56

Sorry, steh am Schlauch was das Problem ist, dachte accelstepper blockiert niemals den Sketch?
Ich dachte geht meist daneben. Einfach mal einen Blick in die Doku werfen. AccelStepper ist gut dokumentiert.

Gruß Tommy
"Wer den schnellen Erfolg sucht, sollte nicht programmieren, sondern Holz hacken." (Quelle unbekannt)

4711

#126
Jun 17, 2019, 04:25 pm Last Edit: Jun 17, 2019, 04:59 pm by 4711
Quote
Moves the motor (with acceleration/deceleration) to the new target position and blocks until it is at position. Dont use this in event loops, since it blocks.
Shit, überlesen
gut, aber habs noch nicht warum .move nicht läuft?
benötigt der stepper einen void loop Daueraufruf mit stepper.run(); ?
Jup, das wars, nun läufts.

Nun möchte ich den Speed des Motors einstellen.
Damit zurück zu den Steps Full/Half. Wenn ich richtig liege sind 400 Halbschritte.
Am Treiber kann ich nun 2/A oder 2/B einstellen, die eine oder andere Wicklung wenn ich das richtig verstehe. Ist das Egal oder hat es eine Bewandnis?
Wenn ich ihn nun mit 2/A fahren lassen, dann knurrt es sehr laut, gefällt mir wenig.

4711

#127
Jun 17, 2019, 05:11 pm Last Edit: Jun 17, 2019, 06:58 pm by 4711
macht grad richtig Laune, dass sich mal was bewegt  :)

nun die Frage, bin ja ein C++ DAU, wie frage ich stepper.isRunning ab ?

Code: [Select]
// Blocking.pde changed!
int PUL=13; //define Pulse pin
int DIR=12; //define Direction pin
int ENA=11; //define Enable Pin
unsigned int iRefState = 0; // Schrittindikator

#include <AccelStepper.h>
AccelStepper stepper(AccelStepper::DRIVER,PUL,DIR);

void setup()

  stepper.setMaxSpeed(10000.0);
  stepper.setAcceleration(1000.0);
  stepper.setEnablePin (ENA); // Pin für das Enable an den Treiber
}

void loop()
{   stepper.run();

    switch (iRefState) {
      case 0:
        stepper.enableOutputs();
        stepper.move (500);
        iRefState++;

      case 1:
        break;
 /*     if (stepper.isRunning () != HIGH)
      {
      iRefState++; 
      }
*/     
      case 2:
        stepper.disableOutputs();
    }
}


.. auch das habe ich nun gefunden.

4711

Wie ist das mit den Eingängen, welche Spannung können die ab?
Ab 2,5V High aber was ist die obere Grenze ohne den Uno zu himmeln?
Kann ein 12V Schalter drauf? Oder nur mit Spannungsteiler Widerstand?

noiasca

welchen Link nutzt du um derartiges herauszufinden?
DE: Wie man Fragen postet:
1. was hat man (Sketch und Hardware)
2. was SOLL es machen
3. was macht es: IST (Fehlverhalten, Fehlermeldungen, Serial.Output ...)
4. Eine Frage stellen bzw. erklären was man erwartet


DrDiettrich

Dann solltest Du dringend genauer lesen lernen. In dem verlinkten Artikel steht nirgends etwas über Spannungen außerhalb 0-5V, außer bei der externen Stromversorgung.

Die Schwelle von 2,5V gibt es in keinem offiziellen Datenblatt. Damit rückt der Artikel verdächtig Richtung fake-news.

noiasca

also ich lese auch in dem Artikel: Signal-Eingänge für digitale Sensoren (5V)

mehr ist nicht.

Methode 3 von hier: https://www.rugged-circuits.com/10-ways-to-destroy-an-arduino
DE: Wie man Fragen postet:
1. was hat man (Sketch und Hardware)
2. was SOLL es machen
3. was macht es: IST (Fehlverhalten, Fehlermeldungen, Serial.Output ...)
4. Eine Frage stellen bzw. erklären was man erwartet

chefin

Die 2,5V Schwelle ist hardware intern festgelegt. Der Designer garantiert ab diesem Schwellwert das er auf 1 umspring, alles drunter auf 0.

Je näher man dieser Schaltschwelle kommt, desdo größer die Störanfälligkeit. Glaub nur nicht das wenn auf deinem Draht mit Multimeter 2,8V anliegen, das ein konstanter Wert ist. Bereits ein Handy da mal eben kurz Alive an den Mobilfunkmasten schickt induziert ne Spannung die deine Werte flackern lässt. Viel zu schnell fürs Multimeter, aber ein µC liest im MHz Bereich, also millionenmal. Der merkt solches Flattern.

Deswegen vergiss das mit den 2,5V schnell wieder. Denk nur Digital, wenn du Digital arbeitest.

Aus MUSS null Volt sein
Ein MUSS 5V sein.

Und nicht mehr. Wenn du 12V Signale hast, dann teile es mit 2 Widerständen runter, aber bleib so nahe es geht an 5V. Es dauert Jahre die Erfahrung zu bekommen, wie weit man die Grenzen ausreizen kann. Menschen lernen Jahre in diesem Beruf bis sie es kapieren. Glaub nur nicht, das wäre so weil sie so langsam lernen. Irgendwann weist du wie weit du Dinge ändern darfst und wie nahe du dich an Grenzwerte bringen kannst, bis es raucht. Dann kommen die 2,5V zum tragen. Aktuell....aus dem Kopf streichen.


DrDiettrich

Die 2,5V Schwelle ist hardware intern festgelegt. Der Designer garantiert ab diesem Schwellwert das er auf 1 umspring, alles drunter auf 0.
Der gleiche Unsinn wie in dem Artikel :-(

Die Schaltschwellen hängen direkt von der Versorgungsspannung ab, und befinden sich nicht in der Mitte des Spannungsbereichs.
Quote
Je näher man dieser Schaltschwelle kommt, desdo größer die Störanfälligkeit.
Das ist reine Theorie, die für andere Controller zutreffen mag. Die ATmega haben jedoch Schmitt-Trigger an den Eingängen und damit eine Hysterese mit 2 Schaltpunkten. Auf dieser Basis funktionieren z.B. die kapazitiven (CapSense) Sensoren.
Quote
Aus MUSS null Volt sein
Ein MUSS 5V sein.
Es wäre hilfreicher, solchen Quatsch nicht weiter zu verbreiten. Wenn jemand tatsächlich Probleme mit Signalpegeln und Störungen hat, dann helfen solche pauschalen Angaben überhaupt nichts.

Ist denn das Lesen und Verstehen von Datenblättern völlig aus der Mode gekommen? Und ersetzt durch das Nachplappern und Liken irgendwelcher Angaben, die irgendwo aufgeschnappt wurden? :-]

Go Up