Hi Community,
bin gerade dabei einen kleinen Plotter zum bemalen von Leiterplatten zu basteln. Die Mechanik habe ich inzwischen recht gut im Griff. Bei der Elektronik sieht es da etwas anderst aus.
Der Schrittmotor scheint immer mal wieder Schritte zu überspringen oder nicht ganz zurecht zukommen.
Die Elektronik ist nach folgendem Schema aufgebaut.
Auf dem Arduino Uno läuft die freie Software GRBL 1.1. Diese gibt die Signale Step, Direction und Enable für jede Achse über ingesamt 9 Pins aus. Diese gebe ich an den Siganlumsetzer weiter. Das ist ein selbst programmierter Atmel ATtiny48-PU. Dieser gibt für jede Achse jeweils die vier Signale zum ansprechen der Motorwindungen aus, welche über einen Schrittmotortreiber an den eigentlichen Schrittmotor 28BYJ-48 weitergegeben werden.
Nachdem ich mich in die Konfiguration von GRBL eingelesen habe und auch schon einiges ausprobiert habe, funktioniert es leider noch nicht so wie es soll. Der Motor kommt immer wieder ins „humpeln“. Meine Vemrutung ist aufgrund der Geräusche des Schrittmotors, dass Schritte übersprungen werden oder mein Eigenbau-Signalumsetzer nicht mit der Frequenz mitkommt. Ein Herabsetzen der Signalgeschwingdigkeit in GRBL hat allerdings auch nicht geholfen.
Man muss dazu sagen, dass es das erste mal ist, dass ich etwas außerhalb der Theorie mit Schrittmotoren zu tun habe.
Den Quellcode von dem Signalumsetzer habe ich unten hinzugefügt. Hoffe ihr könnt mir damit helfen, den Schrittmotor korrekt anzusteuern.
Ich will jetzt hier nicht alles mit Informationen überladen. Solltet ihr zur Beurteilung noch Infos benötigen, schreibt dies gerne. Sofern möglich werde ich diese dann nachliefern.
Der Schrittmotor und die Treiber sollten meiner Einschätzung nicht das Problem sein. Diese wurden als Bundle verkauft.
Im Internet habe ich auch schon Schrittmotor-Signalumsetzer mit integriertem Treiber gesucht, leider vergebens. Vielleicht habt ihr da auch einen Tipp, welche IC´s man da nutzen könnte.
Hoffe Ihr könnt mir helfen das Ding endlich ans laufen zu bekommen.
Viele Grüße
kleinerkaktus
P.S.: Der einfachheit halber, habe ich den Quellcode nur für eine Achse hier eingestellt. Der Qeuellcode ist im richtigen Programm einfach für jede Achse innerhalb der Loop kopiert und die Bezeichnungen der Variablen angepasst worden.
Main.cpp:
/*
* PE.cpp
*/
#include <avr/io.h>
#include <util/delay.h>
#include "ULN2003_Driver.h"
// +++++++++++++++++++++++++++++++++++++++++++++++++++ DEFINITIONS +++++++++++++++++++++++++++++++++++++++++++++++++++
//Frequency CPU
# define F_CPU 16.000;
int main(void)
{
// +++++++++++++++++++++++++++++++++++++++++++++++++++ SETUP +++++++++++++++++++++++++++++++++++++++++++++++++++
initPortsDataDirection();
// +++++++++++++++++++++++++++++++++++++++++++ Variablendeklaration +++++++++++++++++++++++++++++++++++++++++++
//Allgemeine Variable
uint8_t iCountMax = 8;
//X-Achse
bool bXFlankenmerker = false;
bool bXDI_Signal = false;
bool bXDI_Direction = false;
uint8_t iCountX = 1;
// +++++++++++++++++++++++++++++++++++++++++++++++++++ LOOP +++++++++++++++++++++++++++++++++++++++++++++++++++
while (1)
{
// ++++++++++++++++++++++++++++++++++++++++++++ X-Achse +++++++++++++++++++++++++++++++++++++++++++++++++++++++
// >>>>>>>>>>>>> X-Step einlesen (Flanke X) <<<<<<<<<<<<<
bXDI_Signal = (PINB & (1<<PINB5));
bXDI_Direction = (PINB & (1<<PINB4));
if ((bXDI_Signal == true) && (bXFlankenmerker == false))
{
if (bXDI_Direction == true)
{
iCountX++;
}
else
{
iCountX--;
}
bXFlankenmerker = true;
//_delay_ms(5);
}
else if (bXDI_Signal == false)
{
bXFlankenmerker = false;
}
// >>>>>>>>>>>>> Grenzen Zähler festlegen <<<<<<<<<<<<<
if (iCountX > iCountMax)
{
iCountX = 1;
}
else if (iCountX <=0)
{
iCountX = 8;
}
// >>>>>>>>>>>>> Zustände <<<<<<<<<<<<<
switch (iCountX)
{
case 1: XI1_On(); XI2_Off(); XI3_Off(); XI4_Off(); break; //1000
case 2: XI1_On(); XI2_On(); XI3_Off(); XI4_Off(); break; //1100
case 3: XI1_Off(); XI2_On(); XI3_Off(); XI4_Off(); break; //0100
case 4: XI1_Off(); XI2_On(); XI3_On(); XI4_Off(); break; //0110
case 5: XI1_Off(); XI2_Off(); XI3_On(); XI4_Off(); break; //0010
case 6: XI1_Off(); XI2_Off(); XI3_On(); XI4_On(); break; //0011
case 7: XI1_Off(); XI2_Off(); XI3_Off(); XI4_On(); break; //0001
case 8: XI1_On(); XI2_Off(); XI3_Off(); XI4_On(); break; //1001
default: XI1_Off(); XI2_Off(); XI3_Off(); XI4_Off(); break; //0000
}
}
}
Driver:
/*
* ULN2003_Driver.h
*/
#ifndef ULN2003_DRIVER_H_
#define ULN2003_DRIVER_H_
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ DataDirectionsRegister setzen ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
void initPortsDataDirection()
{
////>>>>>>>>>>>>>>>>> Ein-/ Ausgänge definieren --> Data Direction Register (1 - Ausgang, 0-Eingang) <<<<<<<<<<<<<<<<<
//>>>>>>>>>>>>>>>>> X-Achse <<<<<<<<<<<<<<<<<
// PortB: OUTPUTS
DDRB |= (1<<DDB0);
DDRB |= (1<<DDB1);
DDRB |= (1<<DDB2);
DDRB |= (1<<DDB3);
//PortB: INPUTS
DDRB &= ~(1<<DDB4);
DDRB &= ~(1<<DDB5);
}
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Funktionen der Ausgänge ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//X-Achse
void XI1_On(){PORTB |= (1<<PORTB0);}
void XI1_Off(){PORTB &= ~(1<<PORTB0);}
void XI2_On(){PORTB |= (1<<PORTB1);}
void XI2_Off(){PORTB &= ~(1<<PORTB1);}
void XI3_On(){PORTB |= (1<<PORTB2);}
void XI3_Off(){PORTB &= ~(1<<PORTB2);}
void XI4_On(){PORTB |= (1<<PORTB3);}
void XI4_Off(){PORTB &= ~(1<<PORTB3);}
#endif /* ULN2003_DRIVER_H_ */