sketch_70_esp_schrittmotor_servos_ansteuern (ESP8266 NodeMCU)
sketch_70_esp_schrittmotor_servos_ansteuern
/*Ein Roboter mit Schrittmotor (Drehen Hauptachse) sowie 4 Servos wird ueber Eingaben im seriellen Monitor
gesteuert (siehe auch Sketch 62).
Anschluss des Schrittmotors 17HS13-0404S (Schrittwinkel 1,8 Grad) an ESP8266 NodeMCU V2 L293D Motor Shield.
Terminal-Klemmen A- A+ und B- B+.
Anschluss der Servos an die Schiene D-V-G.
Auf Leiterplatte muss die Verbindung von Schiene D-V-G zu 3,3V aufgekratzt werden.
Spannungsversorgung von Netzteil 5V an VIN (Servos) und Akkupack 9V an VM (Schrittmotor).
Der Schrittmotor (Roboter-Drehung) kann in Positionen zwischen "0" und "100" bewegt werden (100 Schritte a 1,8 Grad).
"50" ist die Nullstellung, auch die Startposition.
Der Roboterarm muss vor Einschalten manuell in diese Stellung gedreht werden.
Im seriellen Monitor wird die neue Position eingegeben, z.B. "s100" ("s" fuer SchrittmotorDrehung).
Eingabe "s0" fuehrt zu -90 Grad und "s100" zu +90 Grad.
Durch Anwendung der Variablen "Position_alt" und "Position_neu" wird gewaehrleistet, dass bei jedem neuen Drehbefehl
kein Schritt verloren geht (stets richtiger Schaltzustand der Ausgaenge des L293D).
Es wird der Variablentyp byte verwendet, dadurch Begrenzung des Drehwinkels bei versehentlicher Fehleingabe.
Einstellung der effektiven Spannung an den Wicklungen und damit Strom und Drehmoment ueber PWM-Ausgaenge Pins D1,D2
(max Wert ist 1023 , volle Spannung liegt an).
Beide Spulen sind immer eingeschaltet, in jeder Spule fliesst Strom.
Die Servos werden mit Eingabewerten zwischen ca. 600 und 2600 gesteuert, z.B. Eingabe "g1000" fuer die Stellung des Greifers.
Siehe auch Sketch 62.
Es wird immer nur ein Servo des Roboters bewegt, die anderen bleiben stromlos.
Die "for"-Schleife sorgt dafuer, dass der Servo so lange aktiviert bleibt bis er seine Zielstellung erreicht hat.
Danach haelt er die Position nicht mehr, man kann von Hand verdrehen.
Deshalb kann insbesondere die Achse des Servo "UntenSchwenken" nach Abschalten nach unten wandern, je nach Stellung.
Die jeweilige neue Position wird auch im Serial Monitor angezeigt.
*/
#include "DrehGreifer.h"
#include "SchrittmotorDrehung.h"
#include "Greifer.h"
#include "ObenSchwenken.h"
#include "UntenSchwenken.h"
byte Position_neu;
void setup()
{
pinMode(D1, OUTPUT); // ENA PWM Schrittmotor Wicklung A
pinMode(D2, OUTPUT); // ENB PWM Schrittmotor Wicklung B
pinMode(D3, OUTPUT); // Drehrichtung Wicklung A
pinMode(D4, OUTPUT); // Drehrichtung Wicklung B
pinMode(D5, OUTPUT); // GR Servo Greifer
pinMode(D6, OUTPUT); // DG Servo DrehGreifer
pinMode(D7, OUTPUT); // OS Servo ObenSchwenken
pinMode(D8, OUTPUT); // US Servo UntenSchwenken
Serial.begin(9600); // Initialisierung Serial Monitor(beachte: muss auf 9600 eingestellt sein)
}
void loop()
{
if (Serial.available() > 0) // Wenn Daten vom Serial Monitor da sind (d.h.eingegeben worden sind)...
{
int inByte = Serial.read(); // ...dann lies das erste Byte und speichere es in der Variable inByte
switch (inByte) // und nimm den Wert, der uebertragen wurde, genauer unter die Lupe.
{
case 'd': // wenn dieser das Zeichen (character) 'd' fuer DrehGreifer ist...
{
int PWM_DG = Serial.parseInt(); // dann lies erstmal eine Zahl ein (wenn irgendetwas anders kam, ist das Ergebnis 0)
Serial.print ("DrehGreifer: ");
Serial.println (PWM_DG);
DrehGreifer(PWM_DG);
break; // hoere hier auf.
}
case 's': // wenn dieser das Zeichen (character) 's' fuer SchrittmotorDrehung ist...
{
Position_neu = Serial.parseInt(); // dann lies erstmal eine Zahl ein (wenn irgendetwas anderes kam, ist das Ergebnis 0)
Serial.print ("Drehen auf Position: ");
Serial.println (Position_neu);
SchrittmotorDrehung();
break; // hoere hier auf.
}
case 'g': // wenn dieser das Zeichen (character) 'g' fuer Greifer ist...
{
int PWM_Gr =Serial.parseInt(); // dann lies erstmal eine Zahl ein (wenn irgendetwas anderes kam, ist das Ergebnis 0)
Serial.print ("Greifer: ");
Serial.println (PWM_Gr);
Greifer(PWM_Gr);
break; // hoere hier auf.
}
case 'o': // wenn dieser das Zeichen (character) 'o' fuer ObenSchwenken ist...
{
int PWM_OS =Serial.parseInt(); // dann lies erstmal eine Zahl ein (wenn irgendetwas anderes kam, ist das Ergebnis 0)
Serial.print ("ObenSchwenken: ");
Serial.println (PWM_OS);
ObenSchwenken(PWM_OS);
break; // hoere hier auf.
}
case 'u': // wenn dieser das Zeichen (character) 'u' fuer UntenSchwenken ist...
{
int PWM_US =Serial.parseInt(); // dann lies erstmal eine Zahl ein (wenn irgendetwas anderes kam, ist das Ergebnis 0 )
Serial.print ("UntenSchwenken: ");
Serial.println (PWM_US);
UntenSchwenken(PWM_US);
break; // hoere hier auf.
}
default: // bei unbekannten Kommandos machen wir einfach garnichts...
break;
}
}
}
DrehGreifer.h
void DrehGreifer(int PWM_DG) //vor "PWM_DG" muss nochmal "int" (aber nicht im Hauptprogramm)
{
for(byte i=0; i<=60 ; i++) //Wird i-mal wiederholt, der Servo hat i x 20ms Zeit seine Position zu erreichen
{
digitalWrite(D6,HIGH); // Servo DrehGreifer ist an D6 angeschlossen
delayMicroseconds(PWM_DG); //Zeitvorgabe High-Impuls
digitalWrite(D6,LOW);
delay(19); //Ergaenzung auf Zykluszeit etwa 20ms (delayMicroseconds funktioniert nur bis 16383 "integer")
}
}
Greifer.h
void Greifer(int PWM_Gr) //vor "PWM_Gr" muss nochmal "int" (aber nicht im Hauptprogramm)
{
for(byte i=0; i<=60 ; i++) //Wird i-mal wiederholt, der Servo hat i x 20ms Zeit seine Position zu erreichen
{
digitalWrite(D5,HIGH); // Servo Greifer ist an D5 angeschlossen
delayMicroseconds(PWM_Gr); //Zeitvorgabe High-Impuls
digitalWrite(D5,LOW);
delay(19); //Ergaenzung auf Zykluszeit etwa 20ms (delayMicroseconds funktioniert nur bis 16383 "integer")
}
}
ObenSchwenken.h
void ObenSchwenken(int PWM_OS) //vor "PWM_OS" muss nochmal "int" (aber nicht im Hauptprogramm)
{
for(byte i=0; i<=60 ; i++) //Wird i-mal wiederholt, der Servo hat i x 20ms Zeit seine Position zu erreichen
{
digitalWrite(D7,HIGH); // Servo ObenSchwenken ist an D7 angeschlossen
delayMicroseconds(PWM_OS); //Zeitvorgabe High-Impuls
digitalWrite(D7,LOW);
delay(19); //Ergaenzung auf Zykluszeit etwa 20ms (delayMicroseconds funktioniert nur bis 16383 "integer")
}
}
SchrittmotorDrehung.h
extern byte Position_neu; // neue Position aus dem Hauptprogramm (erneute Deklaration erforderlich)
byte Position_alt= 50; // Startposition "50" bei 0 Grad
byte Schrittzeit = 20; // Variable fuer delay ; 20ms entspricht Schrittfrequenz 50Hz (90 Grad in 1 Sek)
byte Status= 1; // Status 1...4 (PinsD3D4: HH,LL,LH,HL)
void Status_1()
{
digitalWrite(D3,HIGH);
digitalWrite(D4,HIGH);
delay(Schrittzeit);
Status=1;
}
void Status_2()
{
digitalWrite(D3,LOW);
digitalWrite(D4,HIGH);
delay(Schrittzeit);
Status=2;
}
void Status_3()
{
digitalWrite(D3,LOW);
digitalWrite(D4,LOW);
delay(Schrittzeit);
Status=3;
}
void Status_4()
{
digitalWrite(D3,HIGH);
digitalWrite(D4,LOW);
delay(Schrittzeit);
Status=4;
}
void SchrittmotorDrehung()
{
analogWrite (D1,1023);
analogWrite (D2,1023);
int Schritte=Position_neu - Position_alt;
Schritte=abs(Schritte); // Bildung Absolutwert (wenn negativ entfaellt Vorzeichen)
for(byte i=0; i < Schritte; i++)
{
if(Status==1)
{
if(Position_neu-Position_alt>0)
{
Status_2();
}
else
{
Status_4();
}
}
else if(Status==2)
{
if(Position_neu-Position_alt>0)
{
Status_3();
}
else
{
Status_1();
}
}
else if(Status==3)
{
if(Position_neu-Position_alt>0)
{
Status_4();
}
else
{
Status_2();
}
}
else if(Status==4)
{
if(Position_neu-Position_alt>0)
{
Status_1();
}
else
{
Status_3();
}
}
}
Position_alt= Position_neu;
analogWrite (D1,1023); // nach Ende Drehung koennte Strom reduziert werde, aber Motor pfeift
analogWrite (D2,1023);
}
UntenSchwenken.h
void UntenSchwenken(int PWM_US) //vor "PWM_US" muss nochmal "int" (aber nicht im Hauptprogramm)
{
for(byte i=0; i<=60 ; i++) //Wird i-mal wiederholt, der Servo hat i x 20ms Zeit seine Position zu erreichen
{
digitalWrite(D8,HIGH); // Servo UntenSchwenken ist an D8 angeschlossen
delayMicroseconds(PWM_US); //Zeitvorgabe High-Impuls
digitalWrite(D8,LOW);
delay(19); //Ergaenzung auf Zykluszeit etwa 20ms (delayMicroseconds funktioniert nur bis 16383 "integer")
}
}