Servo bewegen met behulp van een Micro Switch

Goedemorgen,

Ik had een aantal vragen.
Voor een project op school wil ik een servomotor laten draaien als de microswitch wordt aangeraakt.
Voordat ik dat programma wil gaan gebruiken wil ik het eerst online simuleren op tinkercad.
Hierbij bestaat er geen micro switch dus maak ik gebruik van een drukknop.

Ik kom niet verder met me programma dan dit, de bedoeling is dus dat mijn Servo pas heen en weer gaat draaien als de drukknop hoog is. De servo mag ook maar 1x heen en weer draaien.
Hieronder de code:

pic basic code:

#include <Servo.h>

Servo mijnServo; // Servo wordt mijnServo genoemd
int buttonPin = 9;


void setup()
{
  mijnServo.attach(8);
  pinMode(buttonPin, INPUT);
}

void loop()
{
  // Servo van 0 naar 180 graden bewegen
  for (int i = 0; i < 180; i++) {
    mijnServo.write(i);
    delay(10);
  }
  
  // Servo van 180 naar 0 graden bewegen
  for (int i = 180; i > 0; i--) {
    mijnServo.write(i);
    delay(10);
  }
}

Wie kan me hiermee helpen, alvast bedankt!

KGE

Golden Member

met

digitalRead(pinnummer)

kun je je knop uitlezen, afhankelijk hoe je hem hebt geschakeld levert dat een LOW of een HIGH op wanneer je de knop indrukt.

Op die basis kun je gaan bepalen wat er moet gebeuren.

  1. "wacht tot knop ingedrukt wordt"
  2. "wanneer knop ingedrukt is, wacht dan net zolang tot de knop weer losgelaten wordt"
  3. "beweeg servo heen en weer"

de loop zorgt ervoor dat dit eindeloos uitgevoerd wordt.

Aan jou de eer om het te vertalen naar 'echte' code..

Ik heb de code aangepast alleen ik weet niet of ik nu op de juiste weg ben..

c code:

#include <Servo.h>

Servo mijnServo; // Servo wordt mijnServo genoemd
int buttonPin = 9;


void setup()
{
  mijnServo.attach(8);
  pinMode(buttonPin, INPUT);
}

void loop(){
  digitalRead(9);
 if (buttonPin == HIGH);
  for(int i = 0; i < 180; i++) { // Servo van 0 naar 180 graden bewegen
    mijnServo.write(i);
    delay(500);
  }
  for(int i = 180; i > 0; i--) { // Servo van 180 naar 0 graden bewegen
    mijnServo.write(i);
    delay(500);
  }
  {
  else (buttonPin == LOW);
    for(int i = 0)
  }
}

Het is beter om gebruik te maken van een interrupt bij invoer van een gebruiker (knopje in dit geval).
Dan weet je zeker dat wat je wil ook uitgevoerd wordt.
Leesvoer:
https://www.arduino.cc/en/Reference/AttachInterrupt

Verder zijn zijn knopjes meestal niet vrij van contactdender.
Je kan dit zowel soft- als hardwarematig oplossen.
Dat laatste wordt hier eenvoudig en in het Nederlands uitgelegd.

Action expresses priorities LH
KGE

Golden Member

Ik zou het niet ingewikkelder maken dan nodig.
Contactdender heb je met deze lange delays geen last van maar om een beetje rust te hebben:

  • wacht tot knop ingedrukt is
  • delay (om contactdender af te wachten)
  • wacht tot knop losgelaten is
  • beweeg servo

Het wachten op een niveau van de knop is in beide gevallen dezelfde instructie alleen met een ander niveau (LOW of HIGH)

Je bent goed op weg, alleen de instructies nog juist gebruiken.

Hint: digitalRead(pinnummer) levert een waarde op die je kunt testen
bijvoorbeeld met 'while'

Microswitch HOOG --> Servo beweegt heen en weer (in 1 beweging zeg maar), mag maar 1x gebeuren
Microswitch LAAG --> Servo staat weer op het beginpunt

c code:

#include <Servo.h>

Servo mijnServo; // Servo wordt mijnServo genoemd
int buttonPin = 9;

void setup()
{
  mijnServo.attach(8);
  pinMode(buttonPin, INPUT);
}

void loop(){
  digitalRead(9);
 while (digitalRead(buttonPin) == HIGH) {
   delay(50); 
  for	(int i = 0; i < 180; i++) { // Servo van 0 naar 180 graden bewegen
    mijnServo.write(i);
    delay(500);
	(int i = 180; i > 0; i--) { // Servo van 180 naar 0 graden bewegen
    mijnServo.write(i);
    delay(500);
  }
  {
  while (digitalRead(buttonPin) == LOW) {
    for(int i = 0)
  }
}
KGE

Golden Member

Je bent er bijna.

Een while 'lus' kan ook gewoon leeg zijn dus zonder { } of een for i=0 er in.

Om aan de voorwaarde voor je knop te voldoen:

zet

while (digitalRead(buttonPin)==LOW);

voor je servo beweegroutine, hij wacht dan net zolang (while is tenslotte engels voor 'zolang') tot je buttonPin van LOW (niet ingedrukt) naar HIGH (wel ingedrukt) gaat.

en met

while (digitalRead(buttonPin)==HIGH);

net onder je servo beweeg code wacht je tot het omgekeerde het geval is (dus tot je de knop weer loslaat).

De regel met digitalRead(9) is overbodig (doet verder niets)

Het geeft een leuk effect als je afhankelijk van de knopstand het aantal graden optelt of aftrekt:

c code:




direction=-1; // standaard gaan we naar beneden..

if (digitalRead(buttonPin) == HIGH) {

  direction=1; // als knop is ingedrukt gaan we omhoog..

} 

if ( 0<i<180 ) {  //alleen als we tussen 0 en 180 zijn doen we iets..

 i = i + direction; 
 mijnServo.write(i);

}

delay(100);


Code aangepast zover ik het dacht te weten, via de simulatie begint hij meteen met roteren dus ergens ga ik nog de fout in...

c code:

#include <Servo.h>

Servo mijnServo; // Servo wordt mijnServo genoemd
int buttonPin = 9;

void setup()
{
  mijnServo.attach(8);
  pinMode(buttonPin, INPUT);
}

void loop()
{
  while (digitalRead(buttonPin) == LOW);
 while (digitalRead(buttonPin) == HIGH); {
   delay(50); 
  for	(int i = 0; i < 180; i++) { // Servo van 0 naar 180 graden bewegen
    mijnServo.write(i);
    delay(500);
	for (int i = 180; i > 0; i--) { // Servo van 180 naar 0 graden bewegen
    mijnServo.write(i);
    delay(500);
  }
 }
 }
}
KGE

Golden Member

Oeh, bijna goed...
Je ziet aan de accolades wel al een beetje dat de structuur niet helemaal lekker zit..

Beetje geschoven met de regels en accolades... :-)

c code:



#include <Servo.h>
 
Servo mijnServo; // Servo wordt mijnServo genoemd
int buttonPin = 9;
 
void setup()
{
  mijnServo.attach(8);
  pinMode(buttonPin, INPUT);
}
 
void loop()
{
  // wacht tot knop ingedrukt wordt
  while (digitalRead(buttonPin) == LOW);

  // Servo van 0 naar 180 graden bewegen
  for	(int i = 0; i < 180; i++) 
  { 
     mijnServo.write(i);
  }

  // even wachten...
  delay(500);

  // Servo van 180 naar 0 graden bewegen
  for (int i = 180; i > 0; i--) 
  { 
     mijnServo.write(i);
  }

  // weer even wachten
  delay(500);
 
  // kijken of knop nog steeds ingedrukt is..
  while (digitalRead(buttonPin) == HIGH); 
 
  // kleine wachttijd voordat we opnieuw beginnen...
  delay(50); 
 
}

Wat kan er nu nog mis gaan ? Hoe zit je knop geschakeld ?

In deze code wordt er vanuit gegaan dat de knop tussen de + van de voeding en de ingang komt te zitten ( de ingang 'pinButton' wordt dan 'HIGH' wanneer de knop ingedrukt wordt)

Maar... De ingang mag, zonder dat de knop ingedrukt is, niet 'zwevend' blijven. Dus daar moet een zgn. pulldown weerstand aan komen van de ingang naar de - van de voeding (GND).
Een weerstand van ongeveer 10 kilo Ohm is ok.

Heel vaak wordt een knop tussen de GND en de ingang gezet, de testvoorwaardes voor HIGH en LOW keren daarbij om. Je kunt dan een ingebouwde 'pullup' weerstand gebruiken die al in de processor zit. Je moet hem alleen aanzetten met:

[code=C]
pinMode(buttonPin, INPUT_PULLUP);
[/code]

Kijk maar eens of dat aan te passen is.

Allereerst heel erg bedankt voor de hulp!

Ik heb het programma nu aangepast en het werkt in de simulatie, echter wanneer ik de simulatie start draait de servo 45 graden.
Komt dit omdat de servo dan naar zijn 0 graden punt toe draait of is het een ander probleem?
De weerstand tussen de knop en de GND is nu 10k Ohm.

c code:

#include <Servo.h>
 
Servo mijnServo; // Servo wordt mijnServo genoemd
int buttonPin = 9;
 
void setup()
{
  mijnServo.attach(8);
  pinMode(buttonPin, INPUT_PULLUP);;
}
 
void loop()
{
  // wacht tot knop ingedrukt wordt
  while (digitalRead(buttonPin) == LOW);
 
  // Servo van 0 naar 180 graden bewegen
  for	(int i = 0; i < 180; i++) 
  { 
     mijnServo.write(i);
  }
 
  // even wachten...
  delay(500);
 
  // Servo van 180 naar 0 graden bewegen
  for (int i = 180; i > 0; i--) 
  { 
     mijnServo.write(i);
  }
 
  // weer even wachten
  delay(500);
 
  // kijken of knop nog steeds ingedrukt is..
  while (digitalRead(buttonPin) == HIGH); 
 
  // kleine wachttijd voordat we opnieuw beginnen...
  delay(50); 
 
}

// Servo van 180 naar 0 graden bewegen
for (int i = 180; i > 0; i--)
{
mijnServo.write(i);
}

Dat hoef je toch niet te doen, gewoon schrijven waar hij naartoe moet zonder fornext.

LDmicro user.

Op 31 oktober 2017 09:56:01 schreef MGP:
[...]
Dat hoef je toch niet te doen, gewoon schrijven waar hij naartoe moet zonder fornext.

Zonder fornext?
Dat begrijp ik niet helemaal..

High met Henk

Special Member

Wat MGP bedoelt is dat je een servo ineens kan positioneren.

dus:

c code:



mijnServo.write(180);

delay(500);

mijnServo.write(0);

Gokje: klasgenoot van GianCain?

die stelt hier ook al vragen en op dezelfde dag aangemeldt en soortgelijk project..

[Bericht gewijzigd door High met Henk op dinsdag 31 oktober 2017 10:45:58 (11%)

E = MC^2, dus de magnetische compatibiliteit doet kwadratisch mee???

Gokje: klasgenoot van GianCain?

die stelt hier ook al vragen en op dezelfde dag aangemeldt en soortgelijk project..

Haha, ja dat klopt.

KGE

Golden Member

Wat je met de servoWrite(s) in de for lus kunt doen is een extra vertraging (delay) inbouwen zodat de servo 'beheerst' van de ene stand naar de andere gaat. Daarom heb ik dat ook niet gewijzigd.

Maar da's het leuke van programmeren, je kunt er van alles aan toevoegen en zien wat het effect is..

De kunst is om de opdracht stap voor stap te vertalen naar je code.
Meestal begin ik met hele grote stappen (of een stroomdiagram) en die dan steeds verder verkleinen en uitwerken naar code.

Op 31 oktober 2017 10:31:20 schreef ArduinoBot1997:
Zonder fornext?
Dat begrijp ik niet helemaal..

In plaats van de variablele i schrijf gewoon waar hij naartoe moet, de for next loop is toch 100den malen sneller dan de servoverplaatsing.

LDmicro user.

Op 31 oktober 2017 11:10:40 schreef MGP:
[...]
In plaats van de variablele i schrijf gewoon waar hij naartoe moet, de for next loop is toch 100den malen sneller dan de servoverplaatsing.

c code:

#include <Servo.h>
 
Servo mijnServo; // Servo wordt mijnServo genoemd
int buttonPin = 9;
 
void setup()
{
  mijnServo.attach(8);
  pinMode(buttonPin, INPUT_PULLUP);;
}
 
void loop()
{
  // wacht tot knop ingedrukt wordt
  while (digitalRead(buttonPin) == LOW);
 
 	mijnServo.write(180);
 
	delay(5000);
 
	mijnServo.write(0);
 
  // weer even wachten
  delay(500);
 
  // kijken of knop nog steeds ingedrukt is..
  while (digitalRead(buttonPin) == HIGH);
 
  // kleine wachttijd voordat we opnieuw beginnen...
  delay(50); 
 

Een accolade vergeten van de loop?

De voorlaatste delay is ook niet nodig omdat je toch kijkt of de drukknop hoog is.

edit: ik vraag mij af, omdat ik geen arduino ervaring heb, of die 180 wel klopt, wat moet je eigenlijk meegeven aan die functie (mijnServo.write() )...graden of...??

LDmicro user.
KGE

Golden Member

Op 31 oktober 2017 12:40:43 schreef MGP:
Een accolade vergeten van de loop?

Denk bij het knippen en plakken...

De voorlaatste delay is ook niet nodig omdat je toch kijkt of de drukknop hoog is.

Er werd al iets over contactdender genoemd, zonder deze delay ga je dat wel merken.

edit: ik vraag mij af, omdat ik geen arduino ervaring heb, of die 180 wel klopt, wat moet je eigenlijk meegeven aan die functie (mijnServo.write() )...graden of...??

Kijk maar eens hier

Op 31 oktober 2017 13:31:09 schreef KGE:

Er werd al iets over contactdender genoemd, zonder deze delay ga je dat wel merken.

Wat gaat die delay(5000) dan doen?

En btw die servo is veel te traag om last te hebben van contactdender, een diesel zonder rook ;)

[Bericht gewijzigd door MGP op dinsdag 31 oktober 2017 13:44:31 (19%)

LDmicro user.

Ik heb de delay op 5 seconden gezet zodat hij pas na 5 seconden terug draait naar 0 graden,
het stond eerst op een halve seconde wachttijd maar daardoor bereikte hij nooit de 180 graden omdat de servo daarvoor te sloom is.
Het kan ook aan het simulatieprogramma liggen want die is ook erg traag.
Het probleem dat de servo uit zichzelf begon te draaien heb ik nu ook opgelost, dit kwam omdat ik bij de void setup niks had vermeld over de beginpositie van de servo.

Tot nu toe heb ik geen vragen meer en denk ik dat mijn code nu klopt, ik wil iedereen bedanken voor het geven van tips en ik ben weer een ervaring rijker. Met name bedankt aan MGP & KGE!

KGE

Golden Member

Op 31 oktober 2017 13:41:46 schreef MGP:
[...]
Wat gaat die delay(5000) dan doen?

En btw die servo is veel te traag om last te hebben van contactdender, een diesel zonder rook ;)

Het is ook niet de delay(5000) die invloed heeft maar wel het feit dat de loop aan het eind rond gaat en de beide digitalRead instructies dus strak achter elkaar aan komen, daar kan contactdender een rol spelen.

KGE

Golden Member

Op 31 oktober 2017 15:12:52 schreef ArduinoBot1997:
Tot nu toe heb ik geen vragen meer en denk ik dat mijn code nu klopt, ik wil iedereen bedanken voor het geven van tips en ik ben weer een ervaring rijker. Met name bedankt aan MGP!

Mooi dat het gelukt is en euh.. graag gedaan ;-)

Op 1 november 2017 00:38:19 schreef KGE:
.. en euh.. graag gedaan ;-)

Je hebt gelijk, ere wie ere toekomt. _o_

LDmicro user.