Code für die Motoren eines Spirograph entwickeln

Ein hallo in die Runde,

nun wird es langsam ernst :wink: und ich weiß es wird ein paar Wochen, evtl. Monate dauern, bis ich mich in die Software-Code eingefunden habe. Hier noch ein mal die Voraussetzungen:

Technische Voraussetzung ist ein Arduino Mega 2560 + RAMPS 1.4 + 4 DRV8255 + LCD im Set plus vier Nema17 Schrittmotoren (Stepper Motor Bipolar 59Ncm 2A; 1,8 deg (200 Stufen / Umdrehung) - Phasenwiderstand: 1.4ohms)

Verwendungszweck für die Entwicklung alle vier Motoren sind festinstalliert und haben unterschiedlich Drehscheiben drauf die sie bewegen, zusammen mit einem Zeichengestänge mit einem Stift.

Ich will langsam anfangen und bräuchte Eure Hilfe, wie man am besten in das Thema einsteigt, evtl. auf welche Code-Beispiele (mobatools wurde schon genannt) ich zurückgreifen sollte usw.

Mache mal einen kurzen Plan auf, wie ich mir die ersten Schritte vorstelle, die ich erlernen sollte:

  1. Ich schreibe einen Code der einen Motor anspricht, der wird gestartet und dreht mit einer bestimmten Geschwindigkeit und schaltet sich nach z.B. 5 sec. selbständig wieder ab.
  2. Ich gebe den Motor 1 auf dem LCD aus.
  3. Ich starte den Motor 1 mit dem LCD, weil das irgendwie den Code auslesen kann.
  4. Motor 1 soll rechts und linksherum laufen
  5. rechts und linksherum soll auf dem LCD ausgegeben werden und auswählbar sein.
  6. Motor 1 kann unterschiedliche Geschwindigkeiten
  7. auf dem LCD kann ich unterschiedliche Geschwindigkeiten auswählen
    usw.

Ich glaube das reicht erst einmal für die ersten Versuche. :roll_eyes:
Wenn ihr damit einverstanden seit, könnte ich das mit Eurer Hilfe nach und nach erlernen bzw. abarbeiten. Wer denkt der Plan ist nicht gut, sollte das bitte auch sagen.

Kommen wir nun zum Punkt 1, wie gehe ich am besten vor um das Ziel zu erreichen, womit sollte ich anfangen?

Beginne beispielsweise mit Stepper_03.ino der MobaTools.

Welchen Displaytyp hast Du? Im Text steht "LCD 2004", abgebildet ist aber "LCD 12864-Anzeigemodul".

Ich hatte Dich ja schon in Deinem Ursprungsthread :wink:
Dann hier meine Variante:
Mache in der Anfangsphase nicht drei Dinge gleichzeitig.
Du willst Werte erfassen, dann diese auswerten und ausgeben.

Das sind drei Schritte.
Freunde Dich mit dem seriellen Monitor an.

Fange mit der Eingabe an.
Also einen Sketch, bei dem Du Werte mit Tasten(?) What ever(?) verändern kannst.

Las Dir die Eingabe-Daten einfach auf dem SerMon anzeigen - fertig.
Wenn das funktioniert, dann die erste Ausgabe auf dem Display.
Da kannst dann Zeile/Spalte etc basteln.

Und dann natürlich die Übergabe an den Treiber...

scheint ein LCD 12864-Anzeigemodul zu sein

Beginne beispielsweise mit Stepper_03.ino der MobaTools.

Erst einmal vielen Dank, für die Antwort.
Hm, habe einiges verstanden in dem Skript und anderes noch nicht.
my_xy_projekt hat wohl recht, die Schritte müssen für mich am Anfang leider noch kleiner sein.

Ich bin mir gar nicht sicher, ob mein LCD überhaupt funktioniert.
Es leuchtet zwar das Display, aber wenn ich den "Hello World!"-Test mit der U8glib.h Bibliothek mache und überprüfe den Code, scheint alles ok. Aber wenn ich ihn dann überspiele, kommt nichts am Display an, statt dessen Blinken zwei LED unten rechts, wie blöd auf dem Ramps.
Hat jemand eine Lösung dafür?

Ja.
Da teilen sich wohl zwei Hardwarebausteine ein und die selbe Schnittstelle.
Dein amazon-Link ist eine Zumutng.
Das was sich dahinter verbirgt ebenfalls.
Da kommt ein bitly - link, der schlussendlich auf ein google-drive .zip verweist.
Da steckt tatsächlich nur ein .ino drin.
Zumindest ist da zu sehen, wieviele Pins schon verwendet werden....

Ok. Um Dir helfen zu können, wäre Dein Code von Vorteil.

Da im ersten Thread einige gegen meine Vorschläge was hatten, halte ich mich hier raus, auch wenn mir die Finger jucken zu helfen, zumindest versuchen.
Ich will nicht nachher auch hier meine Beiträge löschen zu müssen.
Wenn du also nicht weiter kommst, mich erwähnen.

Ok, hier noch aus der RAMPS die verwendeten PIn's.

2,3,8,9,10,12,13,14,15,18,19,24,26,28,30,34,36,38,46,48,53,54,55,56,60,61,62 zudem Analog 13, 14, 15

Du musst jetzt zusehen, das Du für das Display etwas nutzt, was nicht hier rein spielt.

Ja, das glaube ich euch gleich. Tut mir leid, aber ihr konstruiert hier ein Thema am anderen, ohne das irgendwelche Infos, von denen die hier wirklich helfen wollen, auch nur im geringsten beachtet werden. Ihr macht ein Thema nach dem anderen auf, immer wieder das selbe Grundthema, und immer wieder die selben Fragen. Und natürlich auch immer wieder die selben Links, von dem tollen Angebot, das der TS "schon gekauft hat". Aber ich sehe auch, dass sich hier nicht alle verarschen lassen, weil ein paar Leute sich hier raushalten, die eigentlich schon bei ernsthaften Bitten um Hilfe einsteigen. Das zeigt mir dass ich nicht der einzige bin, der diese Veranstaltung für das einstuft, was sie ist. Viel Spass weiterhin. Schade dass ihr das Forum hier für euren Zirkus missbraucht. Spirograph und skorpi.

Schade, man verliert die Lust, bei weiteren Fragestellern einzusteigen, wenn man da das Gefühl hat, nur mitwirkender einer Verkaufsveranstaltung zu werden. Und das gerade dann, wenn das Forum von der Technik her offenbar einen großen Sprung nach vorne gemacht hat. Da ist die Freude über die Verbesserungen in der Forumssoftware kurz, wenn man dann solche Trauerspiele sehen muss.

Wen dem so wäre, bliebe es Dir unbenommen den Thread als "Produktwerbung" zu melden.
Ich sehe das ein wenig anders.
Aber meine Sicht ist ja sowieso grundsätzlich eine andere.

Mir gefällt das ganz und gar nicht, was mir hier von dir Unterstellt wird. Ich mache keine Verkaufveranstaltung, ich möchte mein Projekt umsetzen.
Einige von Euch haben sich über mein erstes Thread aufgereckt, dass es bereits solang ist.
Deshalb habe ich gedacht, ich mach für die jeweiligen Themen eins extra auf, um Euch nicht zu überforden.

Tut mir leid, aber ihr konstruiert hier ein Thema am anderen, ohne das irgendwelche Infos, von denen die hier wirklich helfen wollen , auch nur im geringsten beachtet werden.
Das ist vor allem dann ein Problem, wenn ich eine Frage stelle und man sie scheinbar nicht genau liest oder einige sich nicht in einen völligen Anfänger versetzen können.

Ich bin gerne bereit vieles selbst zu lesen oder mir anzusehen. Aber das Internet erschlägt einen mit teilweise nicht zielführenden Bloggen, Tutorials und Videos. Ich habe danach mehrfach gefragt, um Eure Geduld nicht überzustrappazieren und um Euch auch zu zeigen, das ich mich einfach nur in ein gemachtes Bett legen will.
Aber mir zu unterstellen ich würde ein Verkaufveranstaltung hier abziehen. Sorry wie kann man nur auf so etwas kommen?
Ich werde wohl jetz erst einmal ein bisschen brauchen um das zu verarbeiten.
Und wer Lust hat kann gern zum Thema zurückkommen.

Ein langer Thread stört mich überhaupt nicht.
Aber wenn dann der 2te oder dritte Thread zum selben Thema eröffnet wird, ergreife ich die Flucht.

Ja, und morgen erzähle ich euch ein neues Märchen. Also es sind jetzt schon mindestens 3 Themen, oder vielleicht vier. Spontan fallen mir drei ein, 1. mit 7 Motoren, 2. mit 4 Motoren, 3. Software zum ansteuern der Motoren. Aber macht was ihr wollt. Ich bin raus. Immer nur lesen dass bei dir nichts vorwärts geht, sondern immer nur neue Themen zum selben "Problem". Nicht mit mir.

Ja, das denke ich mir, dass dir das nicht gefällt. Weil es nicht so läuft wie ihr meint, dass es laufen könnte. Wenn du dein Projekt umsetzen möchetst dann zeig mal, wie weit du schon bist. Deine Erklärungen, was du wie haben möchtest ist so ein wirr warr. Weil du gar nichts umsetzen willst. Du hast überhaupt kein Ziel, gibst nur irgend was vor, heute so, morgen so. Einer der wirklich was umsetzen will, wäre inzwischen bei anderen Fragen. Ganz speziell zur Software. Weil er schon erste Programme hätte, die vielleicht noch nicht so laufen wie er meint, dass sie laufen. Aber du trittst auf der Stelle, ineressiert dich überhaut nicht für die Erklärungen die dir gemacht wurden.

Das habe ich leider nicht, daher kann ich Dich da nicht unterstützen.

Hast Du möglicherweise ein 20x4 LCD mit I2C-Schnittstelle rumliegen?

Dann mache ich Dir mal einen Vorschlag basierend auf diesem Beispiel.

Beim DRV8825 habe ich M1 auf HIGH gesetzt für 1/4 Mikroschritt, sonst die Standardbeschaltung. Ich habe Dir zwei Hürden eingebaut:

  1. Weil ich gleichzeitig die MobaTools auf ESP32 teste (es funktioniert!), mußt Du alle Pindefinitionen auf Dein Shield anpassen.
  2. Weil Du mittelfristig vier und langfristig sieben Achsen bewegen möchtest, habe ich erst garnicht mit achse_1 angefangen, sondern besser mit achse[ ACHSE_1 ]. Dann kannst Du Dich gleich damit anfreunden :grinning:
// getestet mit ESP32
/*  Beispiel für die Ansteuerung eines bipolaren Steppers über 4 Taster und
    ein Poti ( für die Geschwindigkeit )
    In diesem Beispiel werden neben der Stepperklasse (MoToStepper), auch die MoToButtons
    und der MoToTimebase genutzt.
    Der Spulenstrom wird abgeschaltet, wenn der Stepper nicht läuft.
    Die Taster müssen gegen Gnd schalten, es sind keine Widerstände notwendig
    Button1:  Dreht rechts, solange Taster gedrückt
    Button2:  Dreht links, solange Taster gedrückt
    Button3:  1 Umdrehung rechts
    Button4:  1 Umdrehung links
*/

#define MAX8BUTTONS // spart Speicher, da nur 4 Taster benötigt werden
#include <MobaTools.h>
// Pindefinitionen - bitte anpassen!
const byte button1Pin   = 25;
const byte button2Pin   = 26;
const byte button3Pin   = 27;
const byte button4Pin   = 14;

const int STEPS_REVOLUTION = 800;                  // 800 Schritte / Umdrehung - 1/4 Microstep

class Achse {
    const byte stepPin, dirPin, enaPin;            // Treiberpins
  public:
    MoToStepper Step;
    Achse(const byte stepPin, const byte dirPin, const byte enaPin)
      : stepPin(stepPin), dirPin(dirPin), enaPin(enaPin), Step( STEPS_REVOLUTION, STEPDIR ) {}
    void init() {
      Step.attach( stepPin, dirPin );
      Step.attachEnable( enaPin, 10, LOW );        // Enable Pin aktivieren ( LOW=aktiv )
      Step.setSpeed( 2000 );                       // 1/10 U/Min
      Step.setRampLen( 50 );                       // Rampenlänge 100 Steps bei 20U/min
    }
};

Achse achse[] {
  //stepPin, dirPin, enaPin; bitte anpassen!
  {32, 33, 13}, // Achse 1
  //{s, d, e}     // Achse n
};

// Taster einrichten
enum { Button1 = 0, Button2, Button3, Button4 } ;  // Den Tasternamen die Indizes 0...3 zuordnen
const byte buttonPins[] = { button1Pin, button2Pin, button3Pin, button4Pin };    // muss als byte definiert sein, damit ein enfaches sizeof funktioniert
MoToButtons button( buttonPins, sizeof(buttonPins), 20, 500 );

MoToTimebase speedIntervall;                       // Zeitinterval zum Auslesen des Speedpotentiometers
// the speed pot ist read only every 'speedintervall' ms

int vspeed = 0;                                    //Steppergeschwindigkeit in U/min*10, könnte variiert werden

void setup()
{
  for (Achse &a : achse) a.init();
  speedIntervall.setBasetime( 100 );               // 100ms Tickerzeit
}

void loop() {
  enum {ACHSE_1};
  button.processButtons();                         // Taster einlesen und bearbeiten

  // Speed alle 100ms neu einlesen und setzen
  if ( speedIntervall.tick() ) {
    // wird alle 100ms aufgerufen ( Tickerzeit = 100ms im setup() )
    vspeed = 1023; //map((analogRead(potPin)), 0, 1023, 20, 1800);  //Poti mappen auf 2 ... 180 Umdr/Min
    //min speed =2 and max speed =180 rpm
    achse[ACHSE_1].Step.setSpeed( vspeed );
  }

  // Drehen rechtsrum
  if (button.pressed(Button1) ) {
    //Taster1 gedrückt
    achse[ACHSE_1].Step.rotate( 1 );               // Stepper dreht vorwärts
  }
  if ( button.released(Button1) ) {
    //Taster1 losgelassen
    achse[ACHSE_1].Step.rotate(0);                 // Stepper stoppt
  }

  //Drehen linksrum
  if (button.pressed(Button2) ) {
    //Taster2 gedrückt
    achse[ACHSE_1].Step.rotate( -1 );              // Stepper dreht rückwärts
  }
  if ( button.released(Button2) ) {
    //Taster2 losgelassen
    achse[ACHSE_1].Step.rotate(0);                 // Stepper stoppt
  }

  // 1 Umdrehung rechts {
  if (button.pressed(Button3) ) {
    //Taster3 wurde gedrückt
    achse[ACHSE_1].Step.doSteps(STEPS_REVOLUTION);
  }

  // 1 Umdrehung links
  if (button.pressed(Button4) ) {
    //Taster4 wurde gedrückt
    achse[ACHSE_1].Step.doSteps(-STEPS_REVOLUTION);
  }
}

Folgende Schritte nun für Dich:

  1. Eine Achse auf dem Shield aussuchen und die zugehörigen Pins ermitteln.
  2. Pinzuordnung mit einer LED mit Vorwiderstand und Blinkprogramm überprüfen.
  3. Im Programm die Pinzuordnung anpassen.
  4. Programm auf dem Mega2560 laden.
  5. Treiber auf das Shield stecken.
  6. Motor anschließen.
  7. Motorspannung am Shield anschließen.
  8. Funktion testen.

Bitte berichte!

Vielen Dank darauf komme ich später noch einmal zurück, wenn ich für mich mehr geklärt habe.
Z.B. ich habe jetzt vier Taster, aber wie und wo kann ich sie am Shield anbringen.
Ja und ich arbeite dran, auch wenn es einige hier nicht glauben. :grinning:

So, ich habe mich ein wenig umgeschaut und etwas eingelesen und getestet.
Wie gesagt ich bin völliger Laie.
Ich habe jetzt meinen ersten Motor zu laufen bekommen. Für mich ein großes Erfolg :trophy: für euch nur sicher nur ein Müdes lächeln.
Einige erste Fragen könnt ihr vielleicht beantworten. Beim Jumper setzen bin ich ein wenig verunsichert, da hier auf der Webseite gesagt wird, alle drei Jumper setzen um 1/32 Microstepping aber auf der englischen reprap.org (RAMPS_1.4) von einem Jumper für 1/16 Microstepping.
Es klingt so als wenn es nur 1/16 unterstützen würde. Was ist richtig?
Ich habe alle drei Jumper bisher gesetzt.

Mein erster Code um den Motor anzusprechen sieht erst einmal so aus:

// einfache Motoransteuerung
#define ENA 38
#define STP 54
#define DIR 55

#define MS1 7
#define MS2 8
#define MS3 9

void setup()
{
pinMode(ENA, OUTPUT); // ENA
pinMode(STP, OUTPUT); // Step
pinMode(DIR, OUTPUT); // Richtung
pinMode(MS1, OUTPUT);
pinMode(MS2, OUTPUT);
pinMode(MS3, OUTPUT);
digitalWrite(ENA,LOW);
digitalWrite(MS1,HIGH);
digitalWrite(MS2,HIGH);
digitalWrite(MS3,HIGH);
}

void loop()
{
digitalWrite(DIR,HIGH);
digitalWrite(STP,HIGH);
delayMicroseconds(80);
digitalWrite(DIR,HIGH);
digitalWrite(STP,LOW);
delayMicroseconds(80);
}

Der Motor dreht sich damit.
Aber wenn ich das MS von LOW auf High setzte, passiert nichts.
Ich denke dass das daran liegt, dass ich das #define MS1 7 einfach aus einem fremden Code übernommen habe. Also, wie wird #define MS1 7 definiert? Was bedeutet die 7, ein Pinplatz? Und wenn ja, wie bekomme ich den heraus für MS1, MS2 und MS3?

Noch eine Frage, wo ist der Unterschied zwischen delay und delayMicroseconds?
Und noch eins, was bedeutet eigentlich wenn ich ENA definiere?
Gut, das war es erst einmal.

Auf deinem Board sind MS1…MS3 gar nicht an den Arduino geführt. Die werden auf dem Board per Jumper gesetzt.

Bei delay(x) ist der Parameter wert in ms. D.h. beo delay(100) bleibt dein Sketch 100ms stehen. Bei delayMicroseconds(100) bleibt er 100µs stehen.

Der ENA-Pin schaltet den Treiber ein und aus. Wenn der enable-Pin am DRB8825 auf HIGH steht, fließt kein Strom durch deinen Motor. Egal was Du an den Step/Dir Pins machst, da passiert dann nichts mehr.

P.S. Ich würde dir auch empfehlen, die Pins nicht mit #define festzulegen, sondern mit const byte ( wie im Sketch von agmue ).

Irgendwie habe ich mir das gedacht. Weil mir nicht klar war, warum ich Jumper setze und dann noch mal ein Microstepping per Code auslöse. Gut dann wird das Ganze übersichtlicher.

Hm, bin noch nicht ganz sicher, ob ich es versteh. Als ich delayMicroseconds benutzte, lief mein Motor deutlich schneller, weil er das sketch schneller abgearbeitet hat und wieder von vorne anfing? Richtig?