• Willkommen im Geoclub - dem größten deutschsprachigen Geocaching-Forum. Registriere dich kostenlos, um alle Inhalte zu sehen und neue Beiträge zu erstellen.

Arduino Programmierung

OP
R

Ranger

Geocacher
Hallo zusammen,

Ich bastel gerade an einem "Tresor" mit einem Arduino, wenn man über ein Keypad eine 4 Stellige Nummer eingibt dann soll ein Servo die Schatzkiste öffnen, soweit geht mein Sketch auch ganz gut, ich hab nur ein Problem wenn der Arduino an die Powerbank angeschlossen wird dreht sich das Servo um ein paar Grad und fährt dann wieder zurück. Diese Drehung kann schon reichen um die Kiste zu öffnen ist dann also unpassend.

Ich hab jetzt versucht das Servo mit einer extra Stromversorgung zu versorgen und nur GND mit dem Arduino zu verbinden, bringt leider keine Besserung.

Wenn ich den Servo an 5volt anschließe ohne Arduino bewegt sich nichts.

Habt ihr ein Tip für mich wie ich das beheben kann das sich beim Starten der Servo nicht bewegt?

Sketch kommt gleich

Vielen Dank
Gruß
Tobias
 
OP
R

Ranger

Geocacher
Der Sketch:

C++:
#include <Keypad.h> // the library for the 4x4 keypad
#include <LiquidCrystal_I2C.h> // the library for the i2c 1602 lcd
#include <Servo.h> // the library to control the servo motor
LiquidCrystal_I2C lcd(0x27, 16, 2); // gets the lcd
Servo servo;
#define Password_Length 5 // the length of the password, if the password is 4 digits long set this to 5
int Position = 0; // position of the servo
char Particular[Password_Length]; // the password length
char Specific[Password_Length] = "2266"; // the password which is called specific in the code, change this to anything you want with the numbers 0-9 and the letters A-D
byte Particular_Count = 0, Specific_Count = 0; // counts the amount of digits and and checks to see if the password is correct
char Key;
const byte ROWS = 4; // the amount of rows on the keypad
const byte COLS = 4; // the amount of columns on the keypad
char keys[ROWS][COLS] = { // sets the rowns and columns
// sets the keypad digits
{'1','2','3','A'},
{'4','5','6','B'},
{'7','8','9','C'},
{'*','0','#','D'}
};
bool SmartDoor = true; // the servo
// the pins to plug the keypad into
byte rowPins[ROWS] = {9, 8, 7, 6};
byte colPins[COLS] = {5, 4, 3, 2};
Keypad myKeypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS); // gets the data from the keypad
// locked charcater
byte Locked[8] = {
B01110,
B10001,
B10001,
B11111,
B11011,
B11011,
B11011,
B11111
};
// open character
byte Opened[8] = {
B01110,
B00001,
B00001, 
B11111,
B11011,
B11011,
B11011,
B11111
};
void setup()
{
servo.attach(12); // attaches the servo to pin 10
ServoClose(); // closes the servo when you say this function
lcd.begin(); // initializes the lcd
lcd.backlight(); // turns on the backlight
lcd.print("Hallo liebe Geocacher"); // prints the text/charater
lcd.setCursor(0,1); // sets the cursor on the lcd
lcd.print("bei T_T_G"); // prints text
delay(7000); // waits 7 seconds
lcd.clear(); // clears the lcd diplay
lcd.print("Habt ihr das "); // prints the text/charater
lcd.setCursor(0,1); // sets the cursor on the lcd
lcd.print("Raetsel geloest?"); // prints text
delay(5000); // waits 5 seconds
lcd.clear(); // clears the lcd diplay
}
void loop()
{
if (SmartDoor == 0) // opens the smart door
{
Key = myKeypad.getKey(); // the word key = myKeypad which gets the value
delay(1000); // waits 1 seconds
{
lcd.clear(); // clears the lcd diplay
ServoClose(); // closes the servo motor
lcd.setCursor(2,0); // sets the cursor on the lcd
lcd.print("fang !!!"); // prints the text to the lcd
lcd.createChar(0, Locked); // prints the locked character
lcd.setCursor(14,0); // sets the cursor on the lcd
lcd.write(0); // prints the first character when you are on the door closed page
delay(3000); // waits 3 seconds
SmartDoor = 1; // closes the door
}
}
else Open(); // keeps the door open
}
void clearData() // clears the data
{
while (Particular_Count != 0) // counts the digits pressed
{
Particular[Particular_Count--] = 0; // counts how many digits
}
return; // returns the data
}
void ServoOpen() // opens the servo
{
for (Position = 120; Position >= 0; Position -= 4) { // moves from 0 to 180 degrees
servo.write(Position); // moves to the postion
delay(15); // waits 15 milliseconds
}
}
void ServoClose() // closes the servo
{
for (Position = 0; Position <= 120; Position += 4) { // moves from position 0 to 180 degrees
servo.write(Position); // moves to the position
delay(15); // waits 15 milliseconds
}
}
void Open() // function declarations
{
lcd.setCursor(1,0); // sets the cursor on the lcd
lcd.print("Der Code ist:"); // prints the text
Key = myKeypad.getKey(); // gets the keys you press from the keypad
if (Key)
{
Particular[Particular_Count] = Key;
lcd.setCursor(Particular_Count, 1); // sets the cursor on the lcd
lcd.print("*"); // prints '*' instead of the password
Particular_Count++; // counts the length of the password
}
if (Particular_Count == Password_Length - 1) // gets the length of the password
{
if (!strcmp(Particular, Specific)) // counts the length and checks to see if the password is correct
{
lcd.clear();
ServoOpen(); // moves the servo 180 degrees
lcd.setCursor(2,0); // sets the cursor on the lcd
lcd.print("richtig");
lcd.createChar(1, Opened);
lcd.setCursor(14,0); // sets the cursor on the lcd
lcd.write(1);
lcd.setCursor(0,1); // sets the cursor on the lcd
lcd.print(" !!! super !!!");
SmartDoor = 0;
}
else
{
lcd.clear();
lcd.setCursor(0,0); // sets the cursor on the lcd
lcd.print("falsch !!!"); // prints the text/character
lcd.setCursor(0,1);
lcd.print("Nochmal in");
lcd.setCursor(13,1);
lcd.print("10");
delay(1000);
lcd.setCursor(13,1);
lcd.print("09");
delay(1000);
lcd.setCursor(13,1);
lcd.print("08");
delay(1000);
lcd.setCursor(13,1);
lcd.print("07");
delay(1000);
lcd.setCursor(13,1);
lcd.print("06");
delay(1000);
lcd.setCursor(13,1);
lcd.print("05");
delay(1000);
lcd.setCursor(13,1);
lcd.print("04");
delay(1000);
lcd.setCursor(13,1);
lcd.print("03");
delay(1000);
lcd.setCursor(13,1);
lcd.print("02");
delay(1000);
lcd.setCursor(13,1);
lcd.print("01");
delay(1000);
lcd.setCursor(13,1);
lcd.print("00");
delay(1000);
lcd.clear();
SmartDoor = 1; // closes the smart door
}
clearData(); // clears the data
}
}
 
Zuletzt bearbeitet von einem Moderator:

capoaira

Geomaster
Ich vermute, dass auf dem Pin eine Spannung liegt, die den Servo bewegt, direkt danach wird Servo close aufgerufen.
Ich würde versuchen mit analogWrite(SERVO_PIN, 0) vor dem Servo.attach() die Spannung auf 0 zu setzten. Dann sollte der Servo am Start sich nicht bewegen
 

Ich_bin_es_nur

Geomaster
Ist schon etwas her, daher muss ich mal vermuten. Werden die Servos vom Arduino beim Programmstart nicht immer bewegt (initilalisiert), damit die aktuelle Stellung bekannt ist. Sollte das so sein, würde ich die Öffnungsbewegung entgegengesetzt programmieren.
 

capoaira

Geomaster
Ergänzung zu meinem letzten post:
Der Pin (in deinem Fall 12) hat einen zufällig Wert zum Start. Diesen musst du bevor du den Servo initialisierst auf den Anfangswert, den der Servo im geschlossenen Zustand hat (also in deinem Fall 120) setzten.
Also vor dem Servo.attach einfach analogWrite(12, 120) schreiben (oder Parameter tauschen, das habe ich gerade nicht im Kopf)
 

Kappler

Geowizard
Ergänzung zu meinem letzten post:
Der Pin (in deinem Fall 12) hat einen zufällig Wert zum Start. Diesen musst du bevor du den Servo initialisierst auf den Anfangswert, den der Servo im geschlossenen Zustand hat (also in deinem Fall 120) setzten.
Also vor dem Servo.attach einfach analogWrite(12, 120) schreiben (oder Parameter tauschen, das habe ich gerade nicht im Kopf)
Das dürfte im Prinzip die Lösung sein, aber da der Servoport kein analoger, sondern ein digitaler (PWM-) Ausgang ist solltest du statt analogWrite(12,120) vor dem servo.attach(12) ein servo.write(120) versuchen (falls das überhaupt vor dem attach-Befehl möglich ist.
 

capoaira

Geomaster
Das dürfte im Prinzip die Lösung sein, aber da der Servoport kein analoger, sondern ein digitaler (PWM-) Ausgang ist solltest du statt analogWrite(12,120) vor dem servo.attach(12) ein servo.write(120) versuchen (falls das überhaupt vor dem attach-Befehl möglich ist.
Ein Servo.write() sollte vor dem initialisieren nicht möglich sein, da ja erst durch den Aufruf von attach() ein Pin für den Servo angegeben wird.
Für PWM Pins nutzt man analogWrite(): https://www.arduino.cc/reference/en/language/functions/analog-io/analogwrite/
 

capoaira

Geomaster
Der Pin (in deinem Fall 12) hat einen zufällig Wert zum Start.
Kleine Korrektur: Ich gehe mal davon aus, dass der Startwert nicht zufällig ist, sonder 0. Der Servo ist aber bei 120 zu. Deshalb muss das vorher installiert werden.
Eventuell reicht es auch anstatt analogWrite Servo.write(120) zu schreiben.

Noch ein kleiner, nett gemeinter Hinweis: Beim Coutdown vor einer erneuten Eingabe, solltest du eine for Schleife verwenden, anstatt 10 mal quasi das selbe zu schreiben. Das würde dir auch ermöglichen, die Wartezeit von Fehlversuch zu Fehlerversuch zu erhöhen. z.B. von 3 auf 5 auf 10. In jedem Fall ist das kürzer und übersichtlicher.
 

schatzi-s

Geowizard
Viele Servos verfahren kurz automatisch, sobald sie Strom haben, auch ohne dass sie speziell angesprochen wurden. Je nach Mechanik kann das schon zu viel sein und das Logbuch frei gegeben werden ...
In diesem Fall hift es, wenn man den Servo nicht konstant mit Strom versorgt, sondern nur, wenn er benoetigt wird. Vin (bzw. Masse) wird also nicht an Dauerplus bzw. Masse gelegt, sondern wird durch eine kleine Transistorschaltung angschlossen und nach Bedarf aktiviert.
(was die Schleife anbelangt hat capoaira natuerlich Recht, ich wuerde mal die These wagen, dass diese Zeile nicht Teil des Originalsketches waren ;-) )
 

Johannis10

Geocacher
Wenn ich das auf die Schnelle richtig sehe:
void ServoClose() // closes the servo
{
for (Position = 0; Position <= 120; Position += 4) { // moves from position 0 to 180 degrees
servo.write(Position); // moves to the position
delay(15); // waits 15 milliseconds
}
Position 120 bedeutet Tresortür zu. (ServoClose)
Position 0 bedeutet Tresortür offen.
Wenn die Tür bereits geschlossen ist und du rufst deine Funktion ServoClose() auf, dann öffnet erstmal die Tresortüre* (Position = 0) und schließt wieder mit der Schleife bis Position = 120 )
Dieser Fall (Tür ist bereits zu und die Funktion ServoClose() wird aufgerufen) tritt bei deinem Setup auf und auch später nochmals...
Grüßle Johannis10
*möglicherweise nicht ganz, wenn das Servo nicht genug Zeit hat, bis die neuen Sollwerte kommen, aber darauf würde ich mich nicht verlassen...
 

Johannis10

Geocacher
Zum Test kannst du deine Funktion mal folgendermaßen abändern, wenn dich schnelles Schließen nicht stört:

void ServoClose() // closes the servo
{
servo.write(120); // moves to the position 120
delay(15); // waits 15 milliseconds
}
 

schatzi-s

Geowizard
oh, da hat Johannis10 Recht!

Ich haette mir das Script ansehen sollen. Ich hatte nur auf die im Text geschriebenen paar Grad reagiert. Ich denke, die kommen daher, dass der Servo an der geschlossen Position ist und dann einfach zu langsam ist. um die jeweiligen Zielpositionen der Schleife zu erreichen. Durch die Schleife wird das Oeffnen "etwas dramatischer" dargestellt, da der Servo gebremst wird.

Die Schleife wird 30x durchlaufen. Das macht 30 mal 15ms also ca. eine halbe Sekunde. Die Zeit wird vermutlich nicht reichen, um das Teil komplett zu oeffnen und dann wieder zu schliessen.

Als praktischen Typ fuer den TO:
void setup()
{
servo.attach(12); // attaches the servo to pin 10
ServoClose(); // closes the servo when you say this function

muss zu

void setup()
{
servo.attach(12); // attaches the servo to pin 12
servo.write(120);

werden.

Dann bewegt sich der Servo direkt auf die Position und versucht nicht vorher an den Anfang zu fahren.

Aber: Ist Pin 12 ueberhaupt PWM faehig und damit Servo geeignet?

P. S.: Danke fuer den Beweis, warum ich Kommentare, die einen Befehl quasi nur wiederholen, nicht mag, da das irgendwann auseinander laeuft: "servo.attach(12); // attaches the servo to pin 10" Was denn nun? 10 oder 12? Aber eine Diskussion ueber Kommentare in einem Programm gehoert hier nicht her ;-)
 

Johannis10

Geocacher
Als praktischen Typ fuer den TO:
void setup()
{
servo.attach(12); // attaches the servo to pin 10
ServoClose(); // closes the servo when you say this function

muss zu

void setup()
{
servo.attach(12); // attaches the servo to pin 12
servo.write(120);

werden.
Wenn ich das richtig sehe genügt eine Änderung im Setup nicht, wenn in der Hauptschleife immer noch die ursprüngliche Funktion "ServoClose()" aufgerufen wird obwohl die Tür zu ist.
 

schatzi-s

Geowizard
Wenn ich das richtig sehe genügt eine Änderung im Setup nicht, wenn in der Hauptschleife immer noch die ursprüngliche Funktion "ServoClose()" aufgerufen wird obwohl die Tür zu ist.
Ich finde das Programm grottig zu lesen (u. A. fehlende Einrueckungen, falsche Kommentare "if (SmartDoor == 0) // opens the smart door", statt //if door is open, schlechte Bezeichner: SmartDoor=0 fuer offene Tuer, statt z. B. DoorOpen usw.).

Aber soweit ich das sehe, wird die Funktion innerhalb der Hauptschleife nur aufgerufen, wenn die Tuer offen ist und geschlossen werden soll.
if (SmartDoor == 0) // opens the smart door {
Key = myKeypad.getKey(); // the word key = myKeypad which gets the value
delay(1000); // waits 1 seconds
{
lcd.clear(); // clears the lcd diplay
ServoClose(); // closes the servo motor
...
}
}
 

capoaira

Geomaster
Ich finde das Programm grottig zu lesen (u. A. fehlende Einrueckungen, falsche Kommentare "if (SmartDoor == 0) // opens the smart door", statt //if door is open, schlechte Bezeichner: SmartDoor=0 fuer offene Tuer, statt z. B. DoorOpen usw.).
Volle Zustimmung.
Ich vermute aber, dass die Einrückung durch das Forum gelöscht wurde, da der Fragesteller den Code nicht in einem Codeblock geschickt hat. Dieser wurde von einem Moderator hinzugefügt.
 

schatzi-s

Geowizard
Ranger: Wenn ich Deine Postings vom Januar mit den aktuellen vergleiche, stelle ich definitiv einen Fortschritt fest. Trotzdem wuerde ich Dir raten, Dich intensiver mit der Programmierung zu beschaeftigen.
Ich bin ehrlich: Ich nutze auch haeufig fertige Demos/ Scripte und passe sie dann an, aber es hilft trotzdem ungemein, wenn man schon eigene Programme geschrieben hat und so z. B. Schleifen und Funktionen verinnerlicht hat.

(ich erinnere mich an eine Situation waehrend des Studiums: Programmierpraktikum ... mir waren die Aufgaben zu langweilig und ich hatte mir die Loesung von jemandem besorgt, aber nicht weiter angeguckt und so sah das Programm bei der Praesentation das erste Mal. Dummerweise fiel das dem Pruefer auf: "Dass Du das nicht selber programmiert hast, ist ja ok, aber hast Du Dir wenigstens die Aufgabe durchgelesen?!" ;-) )
 

Johannis10

Geocacher
Aber soweit ich das sehe, wird die Funktion innerhalb der Hauptschleife nur aufgerufen, wenn die Tuer offen ist und geschlossen werden soll.
Das sehe ich inzwischen auch so. Hatte mir nur ein Teil des Codes angesehen und beim Betrachten eine öffnende geschweifte Klammer, versehentlich als schließende Klammer erkannt und damit die fehlerhafte Schlussfolgerung gezogen.
 
Oben