Stepper-Steuerung mit DM556 Endstufe und UNO

Hier könnt Ihr Erweiterungen und Modifikationen die mit Arduino UNO, Nano etc. realisiert sind vorstellen oder diskutieren.
Benutzeravatar
riu
Administrator
Administrator
Beiträge: 1297
Registriert: Do 4. Sep 2014, 23:48
Wohnort: Düsseldorf
Has thanked: 55 times
Been thanked: 165 times
Kontaktdaten:

Stepper-Steuerung mit DM556 Endstufe und UNO

Beitrag von riu »

Hallo Zusammen.

Ich habe ein Arduino-Projekt was jetzt nicht direkt mit dem RFx000 zu tun hat, aber für eventuelle erweiterungen durchaus interessant werden kann.

Ich möchte meiner BF30 Fräse einen Z-Antrieb verpassen. Dazu habe ich nun folgendes gemacht. Leadshine Endstufe DM556 und 5A Stepper geordert.

Dazu einen original UNO R3 und ein LCD-Display 4x20.

Die Aufgabe ist eigentlich ersteinmal trivial. Es soll ein Poti/Joystick eine Geschwindigkeit vorgeben und der DM556 die Pulse senden. Diese Pilse erzeugen einen Steppuls der an den Stepper signalisiert wird. Steps/Umdrehung, Untersetzung und Weg pro Step werden als Konstanten definiert. Das Display wird per I2C angesteuert und benötigt so eigentlich nur SCL und SDA am Arduino UNO. Die verwendete Lib blockiert aber leider auch A4 und A5 des UNO weil manche Clone SDA und SCL nicht als Pins auf dem Board haben. Das muss man der LIB noch abgewöhnen. Wie? Keine Ahnung :P

Hier ist der Code den ich habe, der aber ohne Interrupts läuft. Das bedeutet wenn der UNO nur die Steppulse ausgeben soll ist es einigermassen flüssig. Muss aber auch das Display angesteuert werden geht es in den Keller mit dem Speed - klar. Alles kann der Kleine nicht im Loop machen.

Also muss ein Timer her um die Steppulse über einen Interrupt zu steuern. Das Poti/Joystick soll den Timer setzen. Also auch hier ein Interrupt. Es soll per Mittenstellung eines 10KOhm Potis nichts passieren. Nach 0 Ohm soll ganz schnell rauf und nach 10KOhm schnell nach unten gefahren werden. Zur mitte in Analog eben lsangsamer werdend.

Ein Schalter für den Eilgang setzt dann noch die Multiplikatoren für den Speed (Schleichgang, Eilgang).

Hier der Code den ich habe, der auch funktioniert aber eben ohne Interrupts.

Code: Alles auswählen

// Parameter und Definitionen nach Gusto anpassen
#include <Wire.h> 
#include <LCD.h>
#include <LiquidCrystal_I2C.h> 



// Ausgangs-Pins
#define READY   13                            // Bereitschaft
#define STEP    12                            // Pin fuer Step-Impuls
#define DIRP    11                            // Pin fuer Richtung
//#define ENABLE   3                            // Pin fuer Enable fuer die Stepper-Endstufe

#define BACKLIGHT_PIN 3
#define En_pin 2
#define Rw_pin 1
#define Rs_pin 0
#define D4_pin 4
#define D5_pin 5
#define D6_pin 6
#define D7_pin 7


// Eingangs-Pins
#define POTI    A1                            // Analogeingang fuer Poti
#define SWITCH  A0                            // Geschwindigkeits-Wahlschalter

// Poti-Paramter
#define Puse    90                            // nutzbarer Drehwinkel des Potis in % (max. 100)
#define Ruhe    20                            // Ruhezone in % (min. 1)
#define MITTE  512                            // ADC-Wert Poti in Mittelstellung
                                              // sollte nicht allzu weit von 512 abweichen
// Schrittfrequenz
#define Fmin     4                            // Minimale Schrittfrequenz - nicht kleiner als 1
#define Fmax  4000                            // Maximale Schrittfrequenz - nicht groesser als 4200
#define RFAKTOR  8                            // Reduktionsfaktor Slow-Mode

#define RICHTUNG 1                            // Richtungsumkehr: auf 0 oder 1 setzen je nach Wunsch                    

#define RELEASE  1                            // Schrittmotor "loslassen" in Ruhestellung? 0/1

// ab hier nichts mehr ändern
#define I2C_ADR_Display 0x27                  // Adresse Display
#define Pmin ((335544L * Ruhe) >> 16)         // Minwert vom Poti
#define Pmax ((335544L * Puse) >> 16)         // Maxwert vom Poti

char cBuffer[5]; // Variablen für LCD Ausgabe

int p, s, l;
int f = Fmax;
long d;

int aRead() {
  int v = analogRead(POTI) - MITTE;           // 0-1023 -> -512 .. +511
  v <<= 2;                                    // ganz einfache Glaettung
  v += l;
  v += l;
  v += l;
  v >>= 2;
  l = v;
  v >>= 2;
  return v;
}

//Displayinstanz lcd erstellen
LiquidCrystal_I2C lcd(I2C_ADR_Display,En_pin,Rw_pin,Rs_pin,D4_pin,D5_pin,D6_pin,D7_pin, BACKLIGHT_PIN, POSITIVE);

void setup() {
  uint8_t i, r;
  pinMode(READY, OUTPUT);                     // Bereitschaftsanzeige
  pinMode(STEP, OUTPUT);                      // Step
  pinMode(DIRP, OUTPUT);                      // Richtungs-Pin
  //disabled by RIU pinMode(ENABLE, OUTPUT);                    // Enable-Pin
  pinMode(SWITCH, INPUT);                     // Geschwindigkeits-Wahlschalter
  digitalWrite(SWITCH, HIGH);                 // Pullup
  //disabled by RIU digitalWrite(ENABLE, LOW);                  // Enable 0
  Wire.begin(); 
  lcd.setBacklightPin(3,POSITIVE);            //LCD init und ausgabe starten
  lcd.setBacklight(1);
  lcd.begin(20,4);                            // oder lcd.begin(16,2); für meine 16/2 Displays
  lcd.clear();
  lcdWrite(0,0,"Initialisiere...");

  while (--i) {                               // Warten bis sich der ADC stabilisiert
    aRead();
    delay(3);
    digitalWrite(READY, (i & 0x40) ? HIGH : LOW);
  }
  lcd.setCursor(0,1);
  lcd.print("ACD stabil...");
  
  if (abs(l) > (Pmin * 4/5)) r++;
  while (r) {                                 // Warten bis Poti stabil in Ruhezone
    aRead();
    if (abs(l) < (Pmin * 4/5)) r++;
    delay(1);
    digitalWrite(READY, (i++ & 0x20) ? HIGH : LOW);
  }
  lcdWrite(2,0,"Poti Mittenstellung!");
  digitalWrite(READY, HIGH);                  // Bereit
    
  lcdWrite(3,0,"Bereit!");
  delay(3000);
  lcdSetup();
}

void loop() {
  p = aRead();                                // geglaetteten Potiwert holen
  lcdWrite(3,0,itoa(p,cBuffer,10));      // Potiwert für Debugging in Zeile 4
  getSpeed();
  digitalWrite(STEP, LOW);                    // Impuls-Pin auf low
#if RICHTUNG > 0
  digitalWrite(DIRP, (p < 0) ? HIGH : LOW);   // Richtungs-Pin fuer Stepper
#else
  digitalWrite(DIRP, (p > 0) ? HIGH : LOW);   // Richtungs-Pin fuer Stepper
#endif
  p = abs(p);                                 // 0 .. 512 -> Geschwindigkeit
  if (p > Pmin) {                             // aus Ruhezone?
    //disabled by RIU digitalWrite(ENABLE, HIGH);               // Enable 1
    p = constrain(p, Pmin, Pmax);             // Werte begrenzen
    if (digitalRead(SWITCH)) {
      lcdWrite(0,8,"Eilgang     ");
      f = map(p, Pmin, Pmax, Fmin, Fmax);     // und Poti -> Frequenz mappen
    } else {
      lcdWrite(0,8,"Schleichgang");
      f = map(p, Pmin, Pmax, Fmin, Fmax / RFAKTOR);
    }
    
    if (f > 63) {                             // delayMicroseconds kann max. 16383us
      d = 1000000L / f;
      d -= 234;                               // Laufzeitkorrektur um 234us
      if (d > 0) delayMicroseconds(d);
    } else {                                  // bei > 16ms keine Laufzeitkorrektur noetig
      delay(1000 / f);
    }
    digitalWrite(STEP, HIGH);                 // Step an Impuls-Pin
#if RELEASE > 0
  } else {
    //disabled by RIU digitalWrite(ENABLE, LOW);                // Enable 0 - "loslassen"
#endif
  }
}

////////////////////////////////////////////////////////
void lcdSetup() {
  lcd.clear();                                // Erstmal alles löschen
  lcdWrite(0,0,"Geschw.:");
  lcdWrite(2,0,"Z Pos  :");
  lcdWrite(2,12,"0,000 mm");
  getSpeed();
}

void getSpeed(){
  if (digitalRead(SWITCH)) {
      lcdWrite(0,8,"Eilgang     ");
    } else {
      lcdWrite(0,8,"Schleichgang");
  }  
}

void lcdWrite (int iRow,int iCol,String sValue){
  lcd.setCursor(iCol,iRow);
  lcd.print(sValue);
}
Hier ein Video von mir mit dem Aufbau.



Frage. Kann ich analogen Eingängen eigentlich einen Interrupt geben?

Das Fritzing mache ich gerade.

Der Hauptcode ist von hier. Die Implementation des LCD ist von mir.

Lieben Gruß,
Udo
Du hast keine ausreichende Berechtigung, um die Dateianhänge dieses Beitrags anzusehen.
Benutzeravatar
JoBo
Globaler Moderator
Globaler Moderator
Beiträge: 448
Registriert: Fr 31. Okt 2014, 13:30
Has thanked: 15 times
Been thanked: 59 times

Re: Stepper-Steuerung mit DM556 Endstufe und UNO

Beitrag von JoBo »

riu hat geschrieben: Das Display wird per I2C angesteuert und benötigt so eigentlich nur SCL und SDA am Arduino UNO. Die verwendete Lib blockiert aber leider auch A4 und A5 des UNO weil manche Clone SDA und SCL nicht als Pins auf dem Board haben. Das muss man der LIB noch abgewöhnen. Wie? Keine Ahnung :P
Der Lib das abzugewöhnen wird nix. Schau dir das Pinmapping an, dann weisst du warum...
riu hat geschrieben: Frage. Kann ich analogen Eingängen eigentlich einen Interrupt geben?
Das sollte gehen, da die analogen Pins entsprechende Doppelfunktionen (PCINTx) haben. Ob Arduino das aber so ohne weiteres mitmacht weiss ich im Moment auch nicht.

Jörg
Benutzeravatar
riu
Administrator
Administrator
Beiträge: 1297
Registriert: Do 4. Sep 2014, 23:48
Wohnort: Düsseldorf
Has thanked: 55 times
Been thanked: 165 times
Kontaktdaten:

Re: Stepper-Steuerung mit DM556 Endstufe und UNO

Beitrag von riu »

Okay, das Pinmapping kannte ich noch nicht. Bin grade mal 4 Tage mit Arduino beschäftigt. Kommt aber alles langsam :P

Gut. Dann sind die Pins eben verloren. Wir haben Ja A0 und A1 mit PCINT8 und PCINT9 ich hoffe das sind Interrupts. Bei Digital 11 und 12 ists auch nicht anders. Eventuell müssen die auf Digi 2 und 3 weil da INT0 und INT1 definitiv Interrupts sind oder. Die Frage ist wie baue ich den Timer. Reicht er interne oder brauche ich noch ein besseres Timininterface? Der UNO ist doch mit 8MHz getaktet oder? Was liegt denn an AREF an? Fragen über Fragen.

Ok ich versuche rauszufinden was PCINT ist und welcher Takt maximal möglich ist.

Lieben Gruß,
Udo
Benutzeravatar
JoBo
Globaler Moderator
Globaler Moderator
Beiträge: 448
Registriert: Fr 31. Okt 2014, 13:30
Has thanked: 15 times
Been thanked: 59 times

Re: Stepper-Steuerung mit DM556 Endstufe und UNO

Beitrag von JoBo »

PCINT steht für Pin Change Interrupt, daher eigentlich egal auf welche pins du dein externes Interruptsignal legst. Der Uno ist mit 16 Mhz getaktet.

Ich überlege gerade, ob das auch mit einem PWM mit variabler Freqenz gehen würde.

Jörg
Benutzeravatar
riu
Administrator
Administrator
Beiträge: 1297
Registriert: Do 4. Sep 2014, 23:48
Wohnort: Düsseldorf
Has thanked: 55 times
Been thanked: 165 times
Kontaktdaten:

Re: Stepper-Steuerung mit DM556 Endstufe und UNO

Beitrag von riu »

Hallo Jörg. Glaube nicht. Bei PWM ändert sich na nur die Pulsweite in millisekunden oder? Das ist kappes. Also wenn ich dem Motor 25.000 schritte pro sekunde senden kann bin ich zufrieden.

Ich werde eine Untersetzung von 1:3,46 haben. 1: ist 4mm Weg (Spindelsteigung). Also brauche ich pro mm Weg 3,46/4 Umdrehungen am Motor. Also 0,856 Umdrehungen. Bein geplanten 800 microsteps 684,8 sind das bei 25kHz satte 36,5 mm/sekunde. Das ist okay finde ich.

Lieben Gruß,
Udo

PS: Ich habe die Schaltskizze an das erste Posting mal angehangen.
Benutzeravatar
JoBo
Globaler Moderator
Globaler Moderator
Beiträge: 448
Registriert: Fr 31. Okt 2014, 13:30
Has thanked: 15 times
Been thanked: 59 times

Re: Stepper-Steuerung mit DM556 Endstufe und UNO

Beitrag von JoBo »

riu hat geschrieben:Bei PWM ändert sich na nur die Pulsweite in millisekunden oder? Das ist kappes. Also wenn ich dem Motor 25.000 schritte pro sekunde senden kann bin ich zufrieden.
Du kannst auch die frequenz ändern (Pins passen evtl. nicht!):

Code: Alles auswählen

// Set pin 9's PWM frequency to 3906 Hz (31250/8 = 3906)
// Note that the base frequency for pins 3, 9, 10, and 11 is 31250 Hz
setPwmFrequency(9, 8);

// Set pin 6's PWM frequency to 62500 Hz (62500/1 = 62500)
// Note that the base frequency for pins 5 and 6 is 62500 Hz
setPwmFrequency(6, 1);

// Set pin 10's PWM frequency to 31 Hz (31250/1024 = 31)
setPwmFrequency(10, 1024);
Duty cicle bei 50% einstellen und nur f in Abhängikeit von R (oder U an A1) ändern sollte gehen. Der Nachteil ist allerdings, dass delay() usw. damit zerschossen werden. Wenn du die aber nicht brauchst...

Jörg

PS: Check mal den Eil/Schleich-Schalter. Da sollte doch bestimmt ein Pin auf Vcc oder?
Benutzeravatar
JoBo
Globaler Moderator
Globaler Moderator
Beiträge: 448
Registriert: Fr 31. Okt 2014, 13:30
Has thanked: 15 times
Been thanked: 59 times

Re: Stepper-Steuerung mit DM556 Endstufe und UNO

Beitrag von JoBo »

Hab da gerade noch eine andere Idee: Warum nicht tone() benutzen. Setzt auch auf den Timern auf und erzeugt ein Rechtecksignal dessen Frequenz du einstellen kannst. Einschränkung: minimal einstellbare Frequenz ist 31 Hz.

Jörg

PS: Vergiss es, ich hab dabei nicht daran gedacht, dass du ja mitzählen willst...
Drall666
Gelegenheitsdrucker
Gelegenheitsdrucker
Beiträge: 32
Registriert: Do 27. Nov 2014, 15:23

Re: Stepper-Steuerung mit DM556 Endstufe und UNO

Beitrag von Drall666 »

Servus Riu,
das Problem hatt ich bei der Regelung unserer Zuluftklappe beim Werkstattofen auch... Geholfen hat die Displayaktualisierung alle 500ms (siehe Beispieldatei im Arduino Programmer " blink without delay")

Grüße,
Andi
Benutzeravatar
riu
Administrator
Administrator
Beiträge: 1297
Registriert: Do 4. Sep 2014, 23:48
Wohnort: Düsseldorf
Has thanked: 55 times
Been thanked: 165 times
Kontaktdaten:

Re: Stepper-Steuerung mit DM556 Endstufe und UNO

Beitrag von riu »

Hallo Andi.

Das ist mir zu langsam. Ich möchte das Display immer dann aktualisiert haben wenn es nicht stört. Der Puls soll über einen Externen Interrupt laufen. Einen Timer interrupt kann man ja mit dem Display kombinieren aber dann so alle 200ms.

Ich werde das mal versuchen aufzubauen.

@JoBo: Ich muss erstmal ein gutes Beispiel mit einem externen Interrupt und dem Speed evtl. in Kombination meit einem Timer um das hinzubekommen. Ich werde morgen mal weiter 'forschen'.

Lieben Gruß,
Udo
Benutzeravatar
Zaldo
Globaler Moderator
Globaler Moderator
Beiträge: 630
Registriert: Do 24. Sep 2015, 10:38
Wohnort: Raum Frankfurt
Has thanked: 38 times
Been thanked: 50 times

Re: Stepper-Steuerung mit DM556 Endstufe und UNO

Beitrag von Zaldo »

Also mit dem Interrupt bei den analogen Eingängen - selbst wenn es geht - habe ich meine Zweifel. Wenn Du einen etwas kippelnden Wert hast, könntest Du Dir mit haufenweise IRQs die CPU unnötig in die Knie zwingen. Das ist bei manchen Inkrementalencodern (die den Rastpunkt genau auf dem Phasenwechsel liegen haben) schon kriminell. Es sei denn, man könnte festlegen ab wieviel digit Änderung ein Interrupt ausgelöst werden soll.
· Besserer Z-Referenzschalter · Druckbett Feinjustage · Platinenkühlung · Weiße Bauraumbeleuchtung · Not-Aus
· Dauerdruckplatte · Temperaturgeregelte Einhausung · Repetier Server auf Raspberry · MK8 Vorschubritzel
Antworten

Zurück zu „Arduino“