Nabend alle beisammen.
Ich bin seid einiger Zeit stiller Mitleser und konnte aus euren Erfahrungen einiges lernen aber gerade stoße ich an meine Grenze.
Was ich probiere ist eigentlich recht simpel.
Ein Servo soll durch betätigen eines Taster von Position 0 ( Startposition ) auf Position 1 fahren.
Bei erneutem betätigen zurück auf 0. Ich habe eine Lösung aber die ist für mich nicht praktikabel. Der Taster muss eine gewisse Zeit gedrückt gehalten werden und beginnt dann den Servo zu steuern. Das Problem ist dass er dann solange der Taster betätigt wird ständig zwischen Pos. 1 und 0 wechselt.
daraufhin war meine Idee heute den Servo wie eine LED zu behandeln und eine LED Pushbuttom Tutorial für den Servo um zu schreiben. aber auch hier fehlanzeige. der Servo beginnt dierekt damit wahrlos zu zittern weil die Befehle wohl zu schnell rein kommen. wenn ich den Taster betätige und gedrückt halte fährt er mal auf Pos. 0 oder 1. Sobald ich den Taster los lasse zittert der Servo wieder.
#include <Servo.h> // zugriff auf Servo Bibliothek
const int BUTTON = 2; // Pushbuttom Pin auf dem Board (2)
int val = 0; // speichert den Zustand des Tasters
int old_val = 0; // speichert den vorherigen wert von val
int state = 0; // 0 = Servo Position eins 1 = Servo Position zwei
Servo servo; // deklariert den Namen des ersten Servos
void setup() {
pinMode(BUTTON, INPUT); // Gibt an dass Buttom ein Input ist
servo.write(0); // gibt die Grundstellung des Servo beim start an
servo.attach(9); // gibt an auf welchem Pin der Servo mit dem steuerkabel anliegt
}
void loop()
{
val = digitalRead(BUTTON); // liest den Input aus und cheked ob er gedrückt ist.
if ((val == HIGH) && (old_val == LOW)){
state = 1 - state;
delay(10);
}
old_val = val; // aktueller val wird zu val alt
if (state == 1) {
servo.write(180); // Stelle servo auf 180 grad
} else {
servo.write(0); // stelle servo auf startposition
}
}
Ich habe mich im Web umgesehen aber finde keinerlei Lösung wobei ich denke doch auf dem richtigem Weg zu sein. Es ist ja viel learning by doing und ein Projekt konnte ich schon realisieren:
aber der Servo ist mir noch ein böhmisches Dorf zu dem ich ein paar Lehrer bräuchte
Edit:
Wenn jemand eine Lösung dazu hat würde ich mich tierisch darüber freuen wenn er/sie mir dabei erklären würde wo genau mein Fehler lag und warum Lösung XY funktioniert des Lerneffektes wegen.
Hallo!
Wie hast du deinen "Button" angeschlossen?
Könnte es sein, dass du den Button an Pin 2 und VCC (also 5 Volt) angeschlossen hast?
Falls es so ist, könnte es dann auch so sein, dass Eingang 2 "in der Luft hängt" wenn der Button nicht gedrückt ist? Das bringt "unerwartete Ergebnisse"
Ein digitaler Eingang muss jederzeit einen definierten Zustand haben. Das bedeutet er muss immer beschaltet sein, wenigstens mit einem Pullup- oder Pulldownwiderstand (z.B. 10 Kiloohm-Widerstand vom Pin auf 5V bzw. auf Masse) oder den internen Pullup aktiviert haben.
Wenn ich deinen Sketch Nr. 2 nehme und den Button an Pin 2 und GND hänge und den Sketch ein wenig ändere, dann funktioniert es (zumindest bei mir):
#include <Servo.h> // zugriff auf Servo Bibliothek
const int BUTTON = 2; // Pushbutton Pin auf dem Board (2)
int val = 0; // speichert den Zustand des Tasters
int old_val = 0; // speichert den vorherigen wert von val
int state = 0; // 0 = Servo Position eins 1 = Servo Position zwei
Servo servo; // deklariert den Namen des ersten Servos
void setup() {
pinMode(BUTTON, INPUT_PULLUP); // Gibt an dass Buttom ein Input ist - DAS IST GEÄNDERT
servo.attach(9); // gibt an auf welchem Pin der Servo mit dem steuerkabel anliegt
servo.write(0); // gibt die Grundstellung des Servo beim start an
}
void loop()
{ val = digitalRead(BUTTON); // liest den Input aus und cheked ob er gedrückt ist.
if ((val == LOW) && (old_val == HIGH)) { // HIER IST DIE ABFRAGE GEÄNDERT
state = 1 - state;
delay(20);
}
old_val = val; // aktueller val wird zu val alt
if (state == 1) {
servo.write(180); // Stelle servo auf 180 grad
}
else {
servo.write(0); // stelle servo auf startposition
}
}
Damit wird der interne Pullup-Widerstand eingeschaltet.
Das ist ein Widerstand von ca. 20-30 Kiloohm der (intern) mit Vcc (5 Volt beim Arduino UNO und anderen) verbunden ist.
In Verbindung mit einem Button (Taster) der nach GND "schaltet" sorgt INPUT_PULLUP dafür, dass der Input Pin HIGH ist, wenn der Taster nicht gedrückt ist - also für einen definierten Pegel ("Pullup" heißt das, weil der Pin sozusagen auf 5 Volt "hinaufgezogen" wird).
Wenn der Taster dann gedrückt wird, wird der Pegel LOW (weil der Taster ja mit GND, also 0 Volt verbunden ist) und auch das ist ein definierter Pegel. So soll es sein
Und: Ja, du warst mit dem Sketch nahe dran
War nur eine Kleinigkeit, eine typische kleine "Stolperfalle" in die wahrscheinlich alle zu Beginn mal tappen.
Damit aktivierst Du den (Controller-internen) Pull-Up-Widerstand des Pins. D. h. es wird ein Widerstand zwischen Pin und Betriebsspannung gesetzt. So ist der Pin HIGH, wenn sonst nichts dort anliegt. Ohne diesen Widerstand hinge der Pin sonst „in der Luft“ und hätte keinen definierten Zustand.
diese Anleitung hat mich super weitergebracht und es hat auf Anhieb funktioniert. Ich bin völliger Arduino Neuling, verstehe aber in Grundzügen was von Programierung. Wie schaffe ich es denn nun, einen zweitern Servo über einen zweiten Taster zu steuern?
Hier mal mein angepasstes Sketch, aber den Zweiten will er nicht steuern?!
Vielen Dank schon mal im Voraus.
Sebastian
#include <Servo.h> // zugriff auf Servo Bibliothek
const int BUTTON = 2; // Pushbutton Pin auf dem Board (2)
int val = 0; // speichert den Zustand des Tasters
int old_val = 0; // speichert den vorherigen wert von val
int state = 0; // 0 = Servo Position eins 1 = Servo Position zwei
Servo servo; // deklariert den Namen des ersten Servos
const int BUTTON2 = 4; // Pushbutton Pin auf dem Board (2)
int val2 = 0; // speichert den Zustand des Tasters
int old_val2 = 0; // speichert den vorherigen wert von val
int state2 = 0; // 0 = Servo Position eins 1 = Servo Position zwei
Servo servo2; // deklariert den Namen des ersten Servos
void setup() {
pinMode(BUTTON, INPUT_PULLUP); // Gibt an dass Buttom ein Input ist - DAS IST GEÄNDERT
servo.attach(9); // gibt an auf welchem Pin der Servo mit dem steuerkabel anliegt
servo.write(0); // gibt die Grundstellung des Servo beim start an
pinMode(BUTTON2, INPUT_PULLUP); // Gibt an dass Buttom ein Input ist - DAS IST GEÄNDERT
servo2.attach(10); // gibt an auf welchem Pin der Servo mit dem steuerkabel anliegt
servo2.write(0); // gibt die Grundstellung des Servo beim start an
}
void loop()
{ val = digitalRead(BUTTON); // liest den Input aus und cheked ob er gedrückt ist.
if ((val == LOW) && (old_val == HIGH)) { // HIER IST DIE ABFRAGE GEÄNDERT
state = 1 - state;
delay(20);
}
old_val = val; // aktueller val wird zu val alt
if (state == 1) {
servo.write(140); // Stelle servo auf 180 grad
}
else {
servo.write(90); // stelle servo auf startposition
}
val = digitalRead(BUTTON2); // liest den Input aus und cheked ob er gedrückt ist.
if ((val2 == LOW) && (old_val2 == HIGH)) { // HIER IST DIE ABFRAGE GEÄNDERT
state2 = 1 - state2;
delay(20);
}
old_val2 = val2; // aktueller val wird zu val alt
if (state2 == 1) {
servo2.write(180); // Stelle servo auf 180 grad
}
else {
servo2.write(0); // stelle servo auf startposition
}
}
Für ein Modellbauprojekt bin ich auf der Suche nach einem Sketch der in etwa genau diesem hier entspricht.
Nun fährt das Servo leider immer mit der schnellstmöglichen Bewegung zum Zielpunkt.
Es wäre besser wenn die Stellgeschwindigkeit über einen Wert programmierbar wäre, ähnlich wie im Servo-Demo-Sketch "sweep"
Nun bin ich leider absoluter Neuling auf diesem Gebiet und habe leider keine Ahnung wie der Sketch aussehen sollte damit das Servo auf Tasterdruck dann langsamer läuft. Der Sketch wäre so schon brauchbar, nur leider zu schnell.
Vielleicht kann jemand helfen?
Vielen Dank, Poly
#include <Servo.h> // zugriff auf Servo Bibliothek
const int BUTTON = 2; // Pushbutton Pin auf dem Board (2)
int val = 0; // speichert den Zustand des Tasters
int old_val = 0; // speichert den vorherigen wert von val
int state = 0; // 0 = Servo Position eins 1 = Servo Position zwei
Servo servo; // deklariert den Namen des ersten Servos
void setup() {
pinMode(BUTTON, INPUT_PULLUP); // Gibt an dass Buttom ein Input ist - DAS IST GEÄNDERT
servo.attach(9); // gibt an auf welchem Pin der Servo mit dem steuerkabel anliegt
servo.write(0); // gibt die Grundstellung des Servo beim start an
}
void loop()
{ val = digitalRead(BUTTON); // liest den Input aus und cheked ob er gedrückt ist.
if ((val == LOW) && (old_val == HIGH)) { // HIER IST DIE ABFRAGE GEÄNDERT
state = 1 - state;
delay(20);
}
old_val = val; // aktueller val wird zu val alt
if (state == 1) {
servo.write(180); // Stelle servo auf 180 grad
}
else {
servo.write(0); // stelle servo auf startposition
}
}
Dann nimm doch das sweep als Vorlage und versuche zu verstehen, was da gemacht wird.
Tip: statt servo.write(ziel) wird servo.write(zwischenschritt) gemacht und der zwischenschritt nur ein bisschen verändert, und ein bisschen gewartet.
int ziel = 0; // 180 oder 0
int akt = 0; // langsame Änderung
void loop()
{ val = digitalRead(BUTTON); // liest den Taster aus und checkt ob er gedrückt ist.
if ((val == LOW) && (old_val == HIGH)) { // Taster neu gedrückt
ziel = 180 - ziel; // springt bei jedem neuen Tasten zwischen 180 und 0 hin und her
delay(20); // entprellen
}
old_val = val; // um Wechsel in val zu erkennen
if (akt != ziel) { // Wenn ziel nicht erreicht ist
if (akt < ziel) akt++; else akt--; // akt nähert sich ziel schrittweise
servo.write(akt);
delay(10) ; // Geschwindigkeit: 1.8 sec für 180 °
}
}
Es gibt mehrere Möglichkeiten.
Eine wäre - genau wie du schon geschrieben hast - es so ähnlich zu machen, wie im Beispiel "Sweep".
Es gibt auch eine Servo-Library, die "langsam fahren" kann. Sie wurde speziell für den Modellbau entwickelt - da hatte also schon mal jemand so ein Problem MobaTools
es gibt wie immer eine einfache Lösung und mehrere mit etwas mehr Aufwand die aber ein flexiebleres Ergebniss liefern.
Wenn der UNO sonst nichts mehr zu tun hat und Du eine Fahrbewegung nicht unterbrechen willst kannst Du mit einer for schleife arbeiten und die gesamte Bewegung damit in kleinere steps unterteilen. Nach jedem step machst Du eine Pause.
Ich habe den Sketch jetzt so zurecht geschrieben und es funktioniert:
const int BUTTON = 2; // Pushbutton Pin auf dem Board (2)
int val = 0; // speichert den Zustand des Tasters
int old_val = 0; // speichert den vorherigen wert von val
int ziel = 1; // 180 oder 0
int akt = 0; // langsame Änderung
Servo servo; // deklariert den Namen des ersten Servos
void setup() {
pinMode(BUTTON, INPUT_PULLUP); // Gibt an dass Buttom ein Input ist - DAS IST GEÄNDERT
servo.attach(9); // gibt an auf welchem Pin der Servo mit dem steuerkabel anliegt
servo.write(1); // gibt die Grundstellung des Servo beim start an
}
void loop()
{ val = digitalRead(BUTTON); // liest den Taster aus und checkt ob er gedrückt ist.
if ((val == LOW) && (old_val == HIGH)) { // Taster neu gedrückt
ziel = 170 - ziel; // springt bei jedem neuen Tasten zwischen 180 und 0 hin und her
delay(20); // entprellen
}
old_val = val; // aktueller val wird zu val alt
if (akt != ziel) { // Wenn ziel nicht erreicht ist
if (akt < ziel) akt++; else akt--; // akt nähert sich ziel schrittweise
servo.write(akt);
delay(20) ; // Geschwindigkeit: 1.8 sec für 180 °
}
}
Auch der Stellweg lässt sich gut über ändern der Werte einstellen. Das ist genau das was ich brauche.
Jetzt muss ich nur schauen wie ich da noch weitere Servos integriert bekomme, aber das dürfte bestimmt kein Problem sein.
Auch der Stellweg lässt sich gut über ändern der Werte einstellen
Konstanten mitten im Code setzt man am besten, so wie z.B. die Pin-Nummer an den Anfang des Sketch mit einem Kommentar. Und verwendet dann diesen Namen.
const int BUTTON = 2; // Pin für den Umschalt-Taster (Anderer Taster-Pin an GND)
const int MIN = 1; // Servo Stellung am Anfang
const int MAX = 170; // Servo Stellung am Ende
const int SPEED = 20; // ms / je Schritt, (MAX-MIN)*SPEED für den gesamten Weg
Und immer drauf achten, dass der Kommentar zum aktuellen Wert passt, denn falsche Kommentare sind schlechter als gar keine.
int ziel = MIN;
...
ziel = MAX+MIN - ziel; // springt zwischen MAX und MIN hin und her
...
delay(SPEED) ; // je höher der Wert, desto langsamer bewegt sich der Servo
Auch der Stellweg lässt sich gut über ändern der Werte einstellen. Das ist genau das was ich brauche.
Jetzt muss ich nur schauen wie ich da noch weitere Servos integriert bekomme, aber das dürfte bestimmt kein Problem sein.
Dann solltest Du sehen das Du das delay raus bekommst. bei einem Delay macht der Prozessor eine Pause und macht sonst nichts mehr. Damit kannst Du dann einen zweiten Servos nicht gleichzeitig laufen lassen.
Schau dir das Beispiel blink without delay an um das delay zu ersetzen. Kannst hier auch mal nach
"mehere Servos betreiben" suchen.
oder versuche es mal mit der hier schon angesprochenen anderen lib für Servos
Aber etwas Gutes hat Dein Video - ich bin nicht schuld - auch in Deiner Werkstatt sind die waagerechten Flächen belegt
Tolles Modell, sauber gearbeitet - gibt's irgendwo einen Rundgang durch Deine Werkstatt?
So zum lange Nase machen? (... und nein ... Gleiches ist bei mir noch lange nicht drin)
postmaster-ino:
Aber etwas Gutes hat Dein Video - ich bin nicht schuld - auch in Deiner Werkstatt sind die waagerechten Flächen belegt
Ja, die Formel dafür ist recht einfach: leere waagerechte Fläche + zu viel Material = alles vollgestellt.
Sowas kann ich schon recht gut beherrschen, nur mit dem Programmieren habe ich noch Probleme.
Aber langsam wird es. Der Sinn liegt darin alle Türen im Körper hintereinander zu öffnen und so wieder zu schließen. Ich habe eine weitere Hilfe eines Bekannten erhalten und jetzt funktioniert alles.