Hallo,
ich habe einen Servo modifiziert (Poti raus und in Nullstellung fixiert sowie Anschläge entfernt)
weil ich 360 grad Drehung brauch. Per Multischalter (RC Fernbedienung) steuer ich den Arduino an um den Servo rechts oder links ganz langsam zu drehen. Das funktioniert auch soweit. Jetzt möchte ich jedoch den links und rechts einen Endlagenschalter verwenden um das Servo zu Stoppen. Später ist auch noch ein Schalter für die Zentrierung geplant.
Der Endlagenschalter müsste also mit in die If Funktion, welche den Multischalter abfragt. Leider steh ich da bissl neben der Spur. Kann mir evtl. jemand helfen?
Hier der Code
#include <Servo.h>
Servo myservo; // Erzeugt ein Objekt des Typs Servo
// maximal 8 Servoobjekte sind möglich
int pos = 110; // Vmax des Servos im Uhrzeigersinn 100 ist neutral muss für jedes Servo individuell angepasst werden
int pos1 = 90; // Vmax des Servos gegen Uhrzeigersinn 100 ist neutral muss für jedes Servo individuell angepasst werden
int pos_muS;
int buttonPIN1 = 2; // Anschluss Multiswitch Kanal 1
int buttonPIN2 = 3; // Anschluss Multiswitch Kanal 2
int buttonPIN3 = 4; // Anschluss Endschalter 1
int buttonPIN4 = 5; // Anschluss Endschalter 2
int val = 0; // variable für lesen des Pin Status
const int buttonPin1 = 2;
const int buttonPin2 = 3;
const int buttonPin3 = 4;
const int buttonPin4 = 5;
int buttonState = 0;
void setup()
{
myservo.attach(9); // gibt den Pin an wo das Servo angeschlossen ist
// es sind alle Pins mit PWM möglich:3,5,6,9,10,11
pinMode(buttonPIN1, INPUT); // legt Art des Einganges fest
pinMode(buttonPIN2, INPUT); // legt Art des Einganges fest
pinMode(buttonPIN3, INPUT); // legt Art des Einganges fest
pinMode(buttonPIN4, INPUT); // legt Art des Einganges fest
}
void loop()
{
val = digitalRead(buttonPin1); // Multischalter Kanal 1 lesen
if (val == LOW) // Wenn Eingang auf LOW
{
pos_muS = map(pos, 0,216,1100,1900); // Umrechnung des Winkels in Microsekunden
myservo.writeMicroseconds(pos_muS); // Variante B senden des PWM Signals an das Servo
delay(10); // 15 Millisekunden warten
}
else
{
myservo.write(90);
}
val = digitalRead(buttonPin2); // Multischalter Kanal 2 lesen
if (val == LOW) // Wenn Eingang auf LOW
{
pos_muS = map(pos1, 0,216,1100,1900); // Umrechnung des Winkels in Microsekunden
myservo.writeMicroseconds(pos_muS); // Variante B senden des PWM Signals an das Servo
delay(10); // 15 Millisekunden warten
}
else
{
myservo.write(90);
}
}
@agmue
Das mit der doppelten Auswahl hab ich geändert. Die Beiden Kanäle des Multischalters können nicht gleichzeitig LOW sein, weil es Kipptaster sind (2/0/1). @drdietrich
Und an welche Stelle füge ich das ein.
Die Funktion brauch ich für ein drehendes Objekt, sodass ich mit den Multischaltern von rechts nach links Schwenken kann bis zu den maximalen Endausschlägen.
murdok1980: @agmue
Das mit der doppelten Auswahl hab ich geändert. Die Beiden Kanäle des Multischalters können nicht gleichzeitig LOW sein, weil es Kipptaster sind (2/0/1).
Dann bekomme ich:
Winkel = 90
pos_muS = 1433
oder
pos_muS = 1507
Winkel = 90
in einem loop! Ich muß nochmal fragen: Soll das so sein?
Ich glaub schon das drehen nach links und rechts funktioniert ja schließlich. Wenn am Code was falsch ist dann sag mir was und warum. Bin noch nicht ganz so firm im programmieren.
Es war ziemlich schwer die interne Servoelektronik zu der langsamen Drehung zu bewegen.
Bei einem Wert von 90 steht der Servo still und die anderen Werte (1433 und 1507) sind für die Drehrichtung links und rechts.
murdok1980:
Wenn am Code was falsch ist dann sag mir was und warum.
Es kann falsch sein oder ich verstehe es nicht, da liegt mein Problem.
val = digitalRead(buttonPin1); // Multischalter Kanal 1 lesen
if (val == LOW) // Wenn Eingang auf LOW
{}
val = digitalRead(buttonPin2); // Multischalter Kanal 2 lesen
if (val == LOW) // Wenn Eingang auf LOW
{}
Diese beiden if kommen direkt nacheinender und schließen sich nicht aus. Darüber stolpere ich.
Unter der Einschränkung, daß ich das Programm nicht wirklich verstehe, mein Endschaltervorschlag:
if (digitalRead(buttonPin3) == LOW || digitalRead(buttonPin4) == LOW) {
// Hier STOPP ausgeben
} else {
val = digitalRead(buttonPin1); // Multischalter Kanal 1 lesen
if (val == LOW) // Wenn Eingang auf LOW
...
Ich fange noch einmal von vorn an, vielleich gibts ja noch ne andere Lösung. Ich habe einen modifizierten Modellbau-Servo der unendlich dreht. Das ausgebaute Poti ist in Nullstellung fixiert somit gibts auch keine Rückmeldung der Servoarmposition. Des weiteren wurden die Endanschläge entfernt.
Diesen Servo will ich mit meiner Fernsteuerung nach links bzw. rechts drehen lassen.
Dafür ist an dem Sender ein Kipptaster, welcher 3 Stellungen hat. Hoch / Neutral / Runter.
Kippe ich den Schalter hoch so soll sich der Servo-Motor so lange nach links drehen wie ich den Schalter nach oben halte, spätestens am linken Endschalter jedoch abschalten.
Kippe ich den Schalter runter so soll sich der Servo-Motor so lange nach rechts drehen wie ich den Schalter nach oben halte, spätestens am rechten Endschalter jedoch abschalten. Quasi so das ich mit dem Hoch/Runter Taster hin und herdrehen kann.
An dem Empfänger befindet sich nun der Multischalter, welcher je einen Ausgang für Hoch/Runter auf LOW schaltet. Diese 2 Ausgänge hängen an den Ports D2 und D3 des Arduino. An D3 kommt der linke Endschalter und an D4 der rechte Endschalter. Auf D9 hängt der Signalanschluss (PWM) des Servos.
Weil die Servoelektronik keine Rückmeldung mehr gibt musste die PWM Ansteuerung manuell machen und mit den Werten experimentieren damit der Servo sehr langsam läuft.
Die Servo Lib liefert da keine brauchbaren Ergebnisse.
Wenn du ne bessere und sauberere Lösung hast bin ich natürlich nicht abgeneigt.
Weltklasse der Code geht habe ihn so hier eingefügt.
#include <Servo.h>
Servo myservo; // Erzeugt ein Objekt des Typs Servo
// maximal 8 Servoobjekte sind möglich
int pos = 110; // Vmax des Servos im Uhrzeigersinn 100 ist neutral muss für jedes Servo individuell angepasst werden
int pos1 = 90; // Vmax des Servos gegen Uhrzeigersinn 100 ist neutral muss für jedes Servo individuell angepasst werden
int pos_muS;
int val = 0; // variable für lesen des Pin Status
const int buttonPin1 = 2; // Anschluss Multiswitch Kanal 1
const int buttonPin2 = 3; // Anschluss Multiswitch Kanal 2
const int buttonPin3 = 4; // Anschluss Endschalter 1
const int buttonPin4 = 5; // Anschluss Endschalter 2
int buttonState = 0;
void setup()
{
myservo.attach(9); // gibt den Pin an wo das Servo angeschlossen ist
// es sind alle Pins mit PWM möglich:3,5,6,9,10,11
pinMode(buttonPin1, INPUT); // legt Art des Einganges fest
pinMode(buttonPin2, INPUT); // legt Art des Einganges fest
pinMode(buttonPin3, INPUT); // legt Art des Einganges fest
pinMode(buttonPin4, INPUT); // legt Art des Einganges fest
}
void loop()
{
if (digitalRead(buttonPin1) == LOW && digitalRead(buttonPin3) == HIGH)
{
pos_muS = map(pos, 0,216,1100,1900); // Umrechnung des Winkels in Microsekunden
myservo.writeMicroseconds(pos_muS); // Variante B senden des PWM Signals an das Servo
delay(10); // 15 Millisekunden warten
}
else if (digitalRead(buttonPin2) == LOW && digitalRead(buttonPin4) == HIGH)
{
pos_muS = map(pos1, 0,216,1100,1900); // Umrechnung des Winkels in Microsekunden
myservo.writeMicroseconds(pos_muS); // Variante B senden des PWM Signals an das Servo
delay(10);
}
else {
myservo.write(90);
}
}
Wenn du mir jetzt noch erklärst was dein Code genau macht hätte ich auch was gelernt ich versteh z.B. nicht was die && bedeuten.
Jetzt brauch ich nur noch nen 3. Schalter für die Mittelstellung programmieren. Wenn ichs nicht hinbekomme frag ich noch einmal nach.
IMO gibt es auch fertige Servos, denen man die Geschwindigkeit vorgeben kann (statt Winkel) - keine Bastelei notwendig. Sonst kannst Du auch beliebige DC Motoren mit einem Motorshield (H-Brücke) ansteuern.
Programmtechnisch würde ich ein Unterprogramm schreiben, dem die Pinnummern und Servo-Objekt als Parameter übergeben werden. Evtl. als Methode einer von Servo abgeleiteten Klasse, dann kann man sich die Parameter-Übergabe auch sparen. Das erfordert dann etwas mehr C++ Kenntnisse, übt aber ungemein
Ich bräuchte nur noch den Schalter für die Mittelstellung einbinden. Das hatte ich schon versucht aber dann funktioniert der Richtungswechsel nicht mehr. Das mit der H-Brücke habe ich Testweise probiert, da war aber das Problem, dass ich die Geschwindigkeit nicht bis auf eine Umdrehung pro Minute runterregeln kann.
Probier ich demnächst aus und melde mich wieder.
Bei der bisherigen Schaltung habe ich Pullup Wiederstände von 5V auf die Digitalports der Schalter gezogen. Die ich die jetzt auf Grund von der Definition im Setup
"pinMode(buttonPin1, INPUT_PULLUP);" wohl weglassen oder?
Versuche nebenbei noch etwas über Interrupts zu lernen aber bis jetzt steig ich da noch nicht durch.
Grüße
Andre
DrDiettrich:
IMO gibt es auch fertige Servos, denen man die Geschwindigkeit vorgeben kann (statt Winkel) - keine Bastelei notwendig.
Danke für den Hinweis, könnte eine Alternative zum Schrittmotor sein.
murdok1980:
Bei der bisherigen Schaltung habe ich Pullup Wiederstände von 5V auf die Digitalports der Schalter gezogen. Die ich die jetzt auf Grund von der Definition im Setup "pinMode(buttonPin1, INPUT_PULLUP);" wohl weglassen oder?
Weil ich faul bin, mache ich es mir zum Testen so einfach wie möglich, dazu gehört "INPUT_PULLUP". Wenn die internen Pullups mit den Digitalports zusammenpassen, ist das OK. Bei den Endschaltern (Öffner) würde ich eher externe Pulldowns verwenden, damit bei der Unterbrechung der Verbindung der Pegel auf LOW = false = Stopp geht.
Dein Programm enthält noch delay(10), was ja "Warten und sonst nix" bedeutet. Auch wenn es möglicherweise keine praktische Auswirkung hat, verträgt sich das grundsätzlich nicht mit Endschaltern, da die Gefahr des Überfahrens oder Überdrehens besteht. Bekommst Du es hin, das durch millis() zu ersetzen? Ich habe zu diesem Thema etwas Prosa geschrieben.
@agmue
Hab den Code jetzt bei mir eingefügt bissl angepasst und funktioniert gut.
Die als Schalteingänge benutzten Ports hab ich alle mit 1kOhm auf +5V gezogen.
Die Endschalter und der Mittelschalter ist jetzt ein Hall Sensor TLE 4905L.
Nun wollte ich noch nen 2. Servo mit anschließen, den der Multischalter parallel mit steuert und welcher seine eigenen Endschalter und Mittelschalter hat.
Den Code hab ich schon versucht anzupassen. Aber mit der weiteren Verschachtelung der Funktionen komme ich nicht klar. Oben im Code hab ich schon die eigene Geschwindigkeit für den zweiten Servo definiert. Aber nun komm ich nicht weiter.
Hier der Code bis jetzt
// Test modifizierter Servo Drehung links und rechts
// Mit Multischalter und Endlagen links und rechts
// Stopp bei erreichen der Mittelstellung
// mit einem Servo gehts schon
#include <Servo.h>
Servo myservo; // Erzeugt ein Objekt des Typs Servo Nummer 1
Servo myservo1; // Erzeugt ein Objekt des Typs Servo Nummer 2
// maximal 8 Servoobjekte sind möglich
int pos = 206; // Vmax des Servos 1 im Uhrzeigersinn ca 200 ist neutral muss für jedes Servo individuell angepasst werden
int pos1 = 198; // Vmax des Servos 1 gegen Uhrzeigersinn ca 200 ist neutral muss für jedes Servo individuell angepasst werden
int pos_muS;
int pos2 = 206; // Vmax des Servos 2 im Uhrzeigersinn ca 200 ist neutral muss für jedes Servo individuell angepasst werden
int pos3 = 198; // Vmax des Servos 2 gegen Uhrzeigersinn ca 200 ist neutral muss für jedes Servo individuell angepasst werden
int pos_muS1;
int val = 0; // variable für lesen des Pin Status
const int buttonPin1 = 2; // Anschluss Multiswitch Kanal 1
const int buttonPin2 = 3; // Anschluss Multiswitch Kanal 2
const int buttonPin3 = 4; // Anschluss Endschalter 1 Servo 1
const int buttonPin4 = 5; // Anschluss Endschalter 2 Servo 1
const int buttonPin5 = 6; // Anschluss Schalter Mitte Servo 1
const int buttonPin6 = 7; // Anschluss Endschalter 1 Servo 2
const int buttonPin7 = 8; // Anschluss Endschalter 2 Servo 2
const int buttonPin8 = 9; // Anschluss Schalter Mitte Servo 2
boolean altPin1;
boolean altPin2;
boolean altPin5;
boolean mitte = false;
boolean altPin8;
boolean mitte2 = false;
int buttonState = 0;
void setup()
{
myservo.attach(10); // gibt den Pin an wo das Servo 1 angeschlossen ist
//myservo1.attach(11); // gibt den Pin an wo das Servo 2 angeschlossen ist
// es sind alle Pins mit PWM möglich:3,5,6,9,10,11
Serial.begin(9600);
pinMode(buttonPin1, INPUT_PULLUP); // legt Art des Einganges fest
pinMode(buttonPin2, INPUT_PULLUP); // legt Art des Einganges fest
pinMode(buttonPin3, INPUT_PULLUP); // legt Art des Einganges fest
pinMode(buttonPin4, INPUT_PULLUP); // legt Art des Einganges fest
pinMode(buttonPin5, INPUT_PULLUP); // legt Art des Einganges fest
altPin1 = digitalRead(buttonPin1);
altPin2 = digitalRead(buttonPin2);
altPin5 = digitalRead(buttonPin5);
altPin8 = digitalRead(buttonPin8);
pinMode(buttonPin6, INPUT_PULLUP); // legt Art des Einganges fest
pinMode(buttonPin7, INPUT_PULLUP); // legt Art des Einganges fest
pinMode(buttonPin8, INPUT_PULLUP); // legt Art des Einganges fest
}
void loop()
{
if (digitalRead(buttonPin5) == LOW && altPin5 == HIGH)
{
mitte = false;
}
else if ((digitalRead(buttonPin1) == LOW && altPin1 == HIGH) || (digitalRead(buttonPin2) == LOW && altPin2 == HIGH))
{
mitte = true;
}
altPin1 = digitalRead(buttonPin1);
altPin2 = digitalRead(buttonPin2);
altPin5 = digitalRead(buttonPin5);
if (digitalRead(buttonPin1) == LOW && digitalRead(buttonPin3) == HIGH && mitte)
{
Serial.println("Links drehen");
pos_muS = map(pos, 0,432,1100,1900); // Umrechnung des Winkels in Microsekunden
myservo.writeMicroseconds(pos_muS); // Variante B senden des PWM Signals an das Servo
//delay(10); // 15 Millisekunden warten
}
else if (digitalRead(buttonPin2) == LOW && digitalRead(buttonPin4) == HIGH && mitte)
{
Serial.println("Rechts drehen");
pos_muS = map(pos1, 0,432,1100,1900); // Umrechnung des Winkels in Microsekunden
myservo.writeMicroseconds(pos_muS); // Variante B senden des PWM Signals an das Servo
//delay(10);
}
else
{
Serial.println("Stop");
myservo.write(90);
}
}
Und dieser müsste quasi mit rein
void loop()
{
if (digitalRead(buttonPin8) == LOW && altPin8 == HIGH)
{
mitte2 = false;
}
else if ((digitalRead(buttonPin1) == LOW && altPin1 == HIGH) || (digitalRead(buttonPin2) == LOW && altPin2 == HIGH))
{
mitte2 = true;
}
altPin1 = digitalRead(buttonPin1);
altPin2 = digitalRead(buttonPin2);
altPin8 = digitalRead(buttonPin8);
if (digitalRead(buttonPin1) == LOW && digitalRead(buttonPin6) == HIGH && mitte2)
{
Serial.println("Links drehen Servo 2");
pos_muS1 = map(pos2, 0,432,1100,1900); // Umrechnung des Winkels in Microsekunden
myservo1.writeMicroseconds(pos_muS1); // Variante B senden des PWM Signals an das Servo
delay(10); // 15 Millisekunden warten
}
else if (digitalRead(buttonPin2) == LOW && digitalRead(buttonPin7) == HIGH && mitte2)
{
Serial.println("Rechts drehen Servo 2");
pos_muS1 = map(pos3, 0,432,1100,1900); // Umrechnung des Winkels in Microsekunden
myservo1.writeMicroseconds(pos_muS1); // Variante B senden des PWM Signals an das Servo
delay(10);
}
else
{
Serial.println("Stop Servo 2");
myservo1.write(90);
}
}