Also hier meine Erkenntnisse:
VRef nicht über 1.3V einstellen
Jeder TMC (3 Stk.) hat einen Kondensator (50V, 220 uF) bekommen.
Ich bin nach viel experimentieren auf folgende Schaltreihenfolge gekommen:
-
Treiber disablen zu beginn
-
24V einschalten (mit einem Relais zum Beispiel), nach dem Booten des Arduinos (in meinem Fall ein Mega 2560)
-
Jetzt kann man die Treiber enablen und ansteuern und danach wieder disablen
Warum das Ganze?
Beim Parallelbetrieb von 2 oder mehr TMCs (ohne irgendeiner Platine/Shield etc.) bricht die Spannung zusammen (Kurzschluss), wenn die 24 V eingeschaltet sind und die Treiber davor enabled wurden. Ich habe die Fehler mit einem Labornetzteil reproduzieren können (damit die Treiber nicht ständig kaputt gehen) und bin mir somit absolut sicher, dass es mit dieser Reihenfolge läuft. Habe es selbst auch so programmiert und tagelang getestet. Das Relais für die 24 V habe ich eingebaut, damit die Motoren während des Bootens des Megas nicht knacksen.
Das hier ist der Code. Die Sachen für die Motoren findet ihr etwas weiter unten. Das ist das EA-Check-Programm für mein gesamtes Projekt
/*
EA-Check
Dieses Programm zeigt die notwendigen Schritte, die in dieser bestimmten, empirisch ermittelten Reihenfolge eingehalten werden müssen,
um Schäden an den Treibern, Motoren oder sonstigen Bauteilen zu verhindern. Die Schritte sind im Programm ebenfalls, wenn notwendig,
kommentiert.
*/
//Bibliotheken einbinden
#include <LiquidCrystal_I2C.h>
//Eingänge
#define ix_ELZ 2 //Check OK
#define ix_ELX 3 //Check OK
#define ix_UP 4 //Check OK
#define ix_DOWN 5 //Check OK
#define ix_OK 6 //Check OK
#define ix_RET 7 //Check OK
#define ix_REF_Z 8 //Check OK
#define ix_REF_X 9 //Check OK
#define ix_Zyl_Ein 10 //Check OK
#define ix_Zyl_Aus 11 //Check OK
//Ausgänge
#define qx_ZylAus 12 //Check OK
#define qx_EnZ1 13 //Check OK
#define qx_StepZ1 14 //Check OK
#define qx_DirZ1 15 //Check OK
#define qx_EnZ2 23 //Check OK
#define qx_StepZ2 19 //Check OK
#define qx_DirZ2 18 //Check OK
#define qx_EnX 22 //Check OK
#define qx_StepX 16 //Check OK
#define qx_DirX 17 //Check OK
#define qx_24V 24 //Check OK
//Variablen
bool Testvar[12];
//Instanzierungen
LiquidCrystal_I2C lcd(0x27, 20, 4); //Check OK
void setup()
{
Serial.begin(9600);
//pinModes
pinMode(ix_ELZ, INPUT_PULLUP);
pinMode(ix_ELX, INPUT_PULLUP);
pinMode(ix_UP, INPUT_PULLUP);
pinMode(ix_DOWN, INPUT_PULLUP);
pinMode(ix_OK, INPUT_PULLUP);
pinMode(ix_RET, INPUT_PULLUP);
pinMode(ix_REF_Z, INPUT_PULLUP);
pinMode(ix_REF_X, INPUT_PULLUP);
pinMode(ix_Zyl_Ein, INPUT_PULLUP);
pinMode(ix_Zyl_Aus, INPUT_PULLUP);
pinMode(qx_ZylAus, OUTPUT);
pinMode(qx_EnX, OUTPUT);
pinMode(qx_StepX, OUTPUT);
pinMode(qx_DirX, OUTPUT);
pinMode(qx_EnZ1, OUTPUT);
pinMode(qx_StepZ1, OUTPUT);
pinMode(qx_DirZ1, OUTPUT);
pinMode(qx_EnZ2, OUTPUT);
pinMode(qx_StepZ2, OUTPUT);
pinMode(qx_DirZ2, OUTPUT);
pinMode(qx_24V, OUTPUT);
//Zu Beginn die 24 V-Versorgung ausschalten
digitalWrite(qx_24V, false);
//LCD-Setup muss vor dem Schalten der Pins geschrieben werden, sonst schalten die 24V ein und aus.
lcd.init();
lcd.backlight();
//LCD Test
/*
Note: lcd.print(); verlangsamt die Motoren, da dürfte ein delay() oder so verwendet werden. Deshalb nur
verwenden, wenn die Motoren nicht angesteuert werden.
*/
lcd.setCursor(0,0);
lcd.print("Hello :D");
//Pins auf einen definierten Zustand bringen
/*
Note: Die Treiber zu Beginn unbedingt disablen (= true). Wenn die Versorgungspannung eingeschaltet wird,
während die Treiber enabled sind, zerstören Stromspitzen die Treiber.
*/
digitalWrite(qx_ZylAus, false);
digitalWrite(qx_EnX, true); //true!!!
digitalWrite(qx_DirX, false);
digitalWrite(qx_StepX, false);
digitalWrite(qx_EnZ1, true); //true!!!
digitalWrite(qx_DirZ1, false);
digitalWrite(qx_StepZ1, false);
digitalWrite(qx_EnZ2, true); //true!!!
digitalWrite(qx_DirZ2, false);
digitalWrite(qx_StepZ2, false);
/*
Note: Das Relais, welches die Versorgungsspannung der Motoren einschaltet, muss unbedingt als letztes im Setup
angesteuert werden.
*/
digitalWrite(qx_24V, true);
Serial.println("Setup End");
}
void loop()
{
if (false)
{ //Input Test
for(byte i = 2; i <= 11; i++)
{
Testvar[i] = !digitalRead(i);
}
//NO Test
for (byte i = 4; i <= 11; i++)
{
if (Testvar[i])
{
Serial.println("Eingang " + String(i) + " aktiv");
delay(250);
}
}
//NC Test
for (byte i = 2; i <= 3; i++)
{
if (!Testvar[i])
{
Serial.println("Eingang " + String(i) + " aktiv");
delay(250);
}
}
//Relais Test, mit OK-Taster angesteuert
digitalWrite(qx_ZylAus, Testvar[6]);
//digitalWrite(qx_24V, Testvar[6]); //Auskommentiert wegen Setup
}
if (false)
{ //Output Test
for (byte i = 13; i <= 19; i++)
{
digitalWrite(i, true);
}
//21 & 22 = LCD SDA und SCL
for (byte i = 22; i <= 23; i++)
{
digitalWrite(i, true);
}
}
//Einzelnes Durchtesten der Ausgänge, weil bei der Verkabelung X und Z2 vertauscht war
//digitalWrite(qx_EnX, true);
//digitalWrite(qx_DirX, true);
//digitalWrite(qx_StepX, true);
//digitalWrite(qx_EnZ1, true);
//digitalWrite(qx_DirZ1, true);
//digitalWrite(qx_StepZ1, true);
//digitalWrite(qx_EnZ2, true);
//digitalWrite(qx_DirZ2, true);
//digitalWrite(qx_StepZ2, true);
//Motor Test
/*
Note: VRef ist auf 1,3 V eingestellt, der Motorstrom begträgt so 200 mA bei 24V.
Um einzelne Motoren oder alle anzusteuern, muss das "false" des jeweiligen if-Blocks
auf true umgeschrieben werden. Mit der OK-Taste kann dann der Motor im Tippbetrieb
betrieben werden.
Funktion der Ansteuerung (der Aufbau ist für alle 4 Möglichkeiten gleich):
1. Treiber einmalig enablen. Ein delay von 5 ms sorgt für einen "knacks"-freien Start.
Weniger als 5 ms funktionieren nicht zuverlässig
2. Richtung (Dir) kann auch einmalig auf die notwendige Richtung geschaltet werden. Muss
nicht, wie hier, zyklisch geschaltet werden
3. Step = true bewegt den Motor. Die Treiber schaltet bei der steigenden Flanke.
4. Die Zeit zwischen Step true und false steuert die Geschwindigkeit. 500 us sind für
die Anwendung vermutlich ausreichend. Mehr ist zu langsam, weniger könnte zu schnell
sein.
5. Wenn die Ansteuerung beendet wird (letztes else if), den/die Treiber disablen. Einfach
nur die Schrittansteuerung abdrehen sollte auch gehen, habe ich aber so nicht getestet.
Treiber enablen braucht keinen delay(), habe ich mit und ohne getestet, kein Unterschied.
Natürlich wäre es schöner, wenn nicht überall digitalRead() stehen würde, habe mich aber
auf die Funktion des Treibers konzentriert und nicht auf eine perfekte Programmstruktur.
Der Ablauf bleibt so oder so gleich.
*/
if (!digitalRead(ix_OK) && (false))
{ //X Motor
if (digitalRead(qx_EnX)) //Wenn der Treiber bereits enabled ist, wird dieses if übersprungen
{
Serial.println("Test X");
digitalWrite(qx_EnX, false);
delay(5); //Ohne delay knackst der Motor beim Wegfahren
}
digitalWrite(qx_DirX, false); //Muss nicht zyklisch geschaltet werden
digitalWrite(qx_StepX, true);
delayMicroseconds(500); //Diese Zeit steuert die Geschwindigkeit des Motors
digitalWrite(qx_StepX, false);
}
else if (!digitalRead(ix_OK) && (false))
{ //Z1 Motor
if (digitalRead(qx_EnZ1))
{
Serial.println("Test Z1");
digitalWrite(qx_EnZ1, false);
delay(5);
}
digitalWrite(qx_DirZ1, false);
digitalWrite(qx_StepZ1, true);
delayMicroseconds(500);
digitalWrite(qx_StepZ1, false);
}
else if (!digitalRead(ix_OK) && (false))
{ //Z2 Motor
if (digitalRead(qx_EnZ2))
{
Serial.println("Test Z2");
digitalWrite(qx_EnZ2, false);
delay(5);
}
digitalWrite(qx_DirZ2, false);
digitalWrite(qx_StepZ2, true);
delayMicroseconds(500);
digitalWrite(qx_StepZ2, false);
}
else if (!digitalRead(ix_OK) && (true))
{ //Alle Motoren
if (digitalRead(qx_EnX) || digitalRead(qx_EnZ1) || digitalRead(qx_EnZ2))
{
digitalWrite(qx_EnX, false);
digitalWrite(qx_EnZ1, false);
digitalWrite(qx_EnZ2, false);
Serial.println("Drivers enabled!");
delay(5);
}
digitalWrite(qx_DirX, false);
digitalWrite(qx_DirZ1, false);
digitalWrite(qx_DirZ2, false);
digitalWrite(qx_StepX, true);
digitalWrite(qx_StepZ1, true);
digitalWrite(qx_StepZ2, true);
delayMicroseconds(500);
digitalWrite(qx_StepX, false);
digitalWrite(qx_StepZ1, false);
digitalWrite(qx_StepZ2, false);
}
else if (!(digitalRead(qx_EnX) && digitalRead(qx_EnZ1) && digitalRead(qx_EnZ2)))
{ //Disable alle Motoren
digitalWrite(qx_EnX, true);
digitalWrite(qx_EnZ1, true);
digitalWrite(qx_EnZ2, true);
Serial.println("Drivers disabled!");
}
}
Ich konnte meine Erkenntnisse so nirgends finden. Vielleicht hilfts jemandem in der Zukunft.