Go Down

Topic: Steuerung "Pushbutton" (Read 4621 times) previous topic - next topic

benelli92

Hey Leute!

Ich habe zwei kurze Fragen zu meinem Projekt:

Ich habe eine DC-Motorsteuerung, welche soweit ganz gut funktioniert. Nun möchte ich aber einen Schalter anschließen, welcher gedrückt werden muss, um das Programm zu starten. Man muss den Schalter gedrückt halten, damit das Programm abläuft. Lässt man den Schalter los, soll das Programm stoppen. Wenn das Programm durchgelaufen ist und man den Schalter los lässt, soll das Programm bei erneutem drücken wieder von vorn starten.
Hat jemand zumindest einen Ansatz, wie man das Programmtechnisch lösen könnte? Ich stehe im Moment leider völlig auf dem Schlauch.

Zum Anschluss des Schalters: Ist es korrekt, dass ich einen Eingang des Schalters mit einem Widerstand (10k Ohm) und Ground, sowie mit dem Pin verbinde und den anderen Eingang des Schalters mit VCC?

Danke!

Muecke

Schau mal hier "Taster richtig abfragen"

dort hast du einen kleinen Schaltplan (Widerstand 1 - 10 kΩ) und du hast gleich die abfrage des Tasters mit drin.


Gruß Mücke

- Anfänger in allen Hinsicht - Bilder sichtbar einstellen
1  Bild Hochladen (Attachements); 2 Beitrag Save; 3 Anhang rechter Mausklick; "Adresse des Links kopieren"; 4 Beitrag „Modify"; 5 img-Tags mit dem kopierten Link einfügen; 6 Beitrag Save
DANKE

sschultewolter

Schaue und lerne die Basics. Dort werden deine Fragen mehr oder weniger komplett gelöst.

Für die Tasterabfrage reicht es, wenn du diesen mit GND und einem I/O verbindest. In der Initialisierung musst du dann bei der Deklarierung des Pins (pinMode) auch noch einem digitalWrite(pin, HIGH) schreiben, damit die internen Pullups genutzt werden.

Den Programmablauf solltest du schon schaffen, selber zu schreiben. Wie bereits gesagt, das sind Basics.
Kümmere dich zuerst um eine ordentliche Entprellung deines Tasters. Entweder mit kleinen delays oder einer besserer Entprellung mit millis().

Das PAP ist relativ trivial. (ohne Berücksichtung der Invertierung bei internen Pullups)
1) Taster einlesen
2) Positive Flanke und Programm nicht aktiv -> Programm ausführen
3) Negative Flanke -> Programm beenden

Gedrückthalten des Tasters hat dann keinen Effekt auf ein erneutes Programm starten. Der Taster muss erneut gedrückt werden.

http://playground.arduino.cc/
Orginal Atmel AVRISP mkII zu verkaufen. Anfrage per PN ;)

Doc_Arduino

Hallo,

guck Dir mal die "Bounce 2" Library an.   https://github.com/thomasfredericks/Bounce-Arduino-Wiring

Davon arbeitest Du die enthaltenen Beispiele durch und kannst das dann für Dein Vorhaben verwenden.


Tschau
Doc Arduino '\0'

Messschieber auslesen: http://forum.arduino.cc/index.php?topic=273445
EA-DOGM Display - Demos: http://forum.arduino.cc/index.php?topic=378279

benelli92

Ok super. Vielen Dank.
Ich schaue mal alles durch und bei Fragen melde ich ich noch einmal ;)

benelli92

Hey Leute,
meine Teile sind nun da und ich bin schon etwas weiter, jedoch habe ich nun ein kleines Problem.
ich nutze nun anstatt des DC-Motors doch einen Schrittmotor. Für die Entprellung des Tasters habe ich die Bounce2 Library genutzt.
Der Motor soll nun Testweise ein paar Schritte vorwärts fahren, warten und wieder ein paar Schritte rückwärts fahren.

Hier der Code:
Code: [Select]
#include <Bounce2.h>
#define BUTTON_PIN 2
int M1dirpin = 4;
int M1steppin = 5;
int j;
int k;


Bounce debouncer = Bounce();

void setup()
{

  pinMode(BUTTON_PIN,INPUT_PULLUP);
  pinMode(M1dirpin,OUTPUT);
  pinMode(M1steppin,OUTPUT);

  debouncer.attach(BUTTON_PIN);
  debouncer.interval(1);
}

void loop()
{

  debouncer.update();

  int button1 = debouncer.read();

  if ( button1 == LOW )
  {

      digitalWrite(M1dirpin,HIGH);
      for(j=0;j<=100;j++)
    {
      digitalWrite(M1steppin,LOW);
      delayMicroseconds(1000);
      digitalWrite(M1steppin,HIGH);
      delayMicroseconds(1000);
    }
    delay (5000);
      digitalWrite(M1dirpin,LOW);
      for(k=0;k<=100;k++)
    {
      digitalWrite(M1steppin,LOW);
      delayMicroseconds(1000);
      digitalWrite(M1steppin,HIGH);
      delayMicroseconds(1000);
    }
  } 


Mein Problem ist nun, dass der Motor die Schleife zwei mal durchläuft, d.h er fährt nun nach betätigen des Tasters vor, pause, zurück, vor, pause, zurück.
Woran könnte das liegen?

Vielen Dank!

Tchefter

Moin moin,

hab grad so was ähnliches vor mir liegen.

Schau mal ob dir das weiterhilft:

Sparkfun Easy Driver - Code by Brian Schmalz

Gruß Fritz

benelli92

hm leider hilft mir das nicht wirklich bei meinem Problem  :(

benelli92

sorry für den Doppelpost.
Bin grad echt am verzweifeln  :smiley-twist: 
Weiss denn niemand, warum der loop immer genau doppelt durchlaufen wird? ich kann es mir echt nicht erklären.

Danke!

Tchefter

mit welchem Treiber steuerst dein Stepper an?
Beispiel 2 von Brian sollte für dich funktionieren.
Du musst halt noch den Button einbauen oder das Bsp.2 bei dir einbauen...
Gruß Fritz

Tchefter

Probiere das mal aus - Du musst noch die PINS entsprechend anpassen
Sowie die Pause zwischen Vor und Zurück und wie schnell der Stepper läuft.
Das ist das Bsp. 2 in deinen Code eingebaut. Muss evtl. noch verfeinert werden...

Code: [Select]



#include <Bounce2.h>
#define BUTTON_PIN 13

int Distance = 0;  // Record the number of steps we've taken

Bounce debouncer = Bounce();

void setup()
{

  pinMode(BUTTON_PIN,INPUT_PULLUP);
 
  pinMode(6, OUTPUT);    // DIR PIN
  pinMode(7, OUTPUT);    // STEP PIN
  digitalWrite(6, LOW);  // DIR PIN
  digitalWrite(7, LOW);  // STEP PIN


  debouncer.attach(BUTTON_PIN);
  debouncer.interval(100);
}

void loop()
{

  debouncer.update();

  int button1 = debouncer.read();

  if ( button1 == LOW )     
  {
  digitalWrite(7, HIGH);
  delayMicroseconds(100);      // Wie schnell soll der Stepper laufen   
  digitalWrite(7, LOW);
  delayMicroseconds(100);      // Wie schnell soll der Stepper laufen
  Distance = Distance + 1;   // record this step
 
  // Check to see if we are at the end of our move
  if (Distance == 400) // Wie WEIT / Wieviel Schritte soll der Stepper laufen
  {
    // We are! Reverse direction (invert DIR signal)
    if (digitalRead(6) == LOW)
    {
      digitalWrite(6, HIGH);
    }
    else
    {
      digitalWrite(6, LOW);
    }
    // Reset our distance back to zero since we're
    // starting a new move
    Distance = 0;
    // Now pause for a second
    delay(1000); // PAUSE ZWISCHEN VOR UND ZURÜCK
  }
}
 
  } 



Gruß Fritz

michael_x

#11
Jan 06, 2015, 03:04 pm Last Edit: Jan 06, 2015, 03:10 pm by michael_x
Quote
Weiss denn niemand, warum der loop immer genau doppelt durchlaufen wird? ich kann es mir echt nicht erklären.
Wofür nimmst du die Bounce library, wenn du delay(5000) verwendest ?

debouncer.update() macht nur Sinn ohne delay.

https://github.com/thomasfredericks/Bounce-Arduino-Wiring/wiki

Da die stable_interval Zeit ohne update() noch nicht erkannt wurde, liefert beim 2. loop Durchlauf nach dem ersten LOW-Trigger bouncer.read() immer noch LOW.


Wenn dir egal ist, dass der Taster tot ist während dein Schrittmotor Vor-Pause-Zurück durchnudelt, dann vergiss bounce und mach einfach
  if (digitalRead(BUTTON_PIN) == LOW)

Alternativ ( und allgemein besser ):  Schreib deinen sketch so um, dass ein loop-Durchlauf nur einen
Motorschritt lang dauert. Also keine for Schleife, sondern nur einmal delayMicroseconds(1000);
und die Schrittnummer und Phase ( VOR / PAUSE / RUECK )  in globalen oder statischen Variablen.
Nachtrag: Etwa so wie Tschefters Vorschlag gerade eben ...

Übrigens ist auch dann ein  debouncer.interval(1); ziemlich sinnlos.
Aber vielleicht willst du ja den Schrittmotor schneller oder den Bouncer träger  machen können...

Nur so könntest du übrigens NOT-AUS, Endschalter oder andere Sachen realisieren, die aktiv sein sollen während dein "Programm" läuft.

Doc_Arduino

#12
Jan 06, 2015, 06:31 pm Last Edit: Jan 06, 2015, 06:31 pm by Doc_Arduino
Hallo,

noch ein Bsp. ohne delay, wie man eine LED ohne delay blinken lassen kann. Vielleicht hilft Dir das weiter.
Wenn Du die Funktion in loop aufrufen läßt, "taktet" die LED ohne die loop mit künstlichen delays zu blockieren. Mußt nur noch einen Pin für "Flash_LED" definieren.
Ob mein Bsp. nun das non plus ultra ist weis ich auch nicht, aber wenn man so ein Grundgerüst vom Ablauf her verstanden hat, kann man sämtliche benötigten Verzögerungen ohne delay machen.

Code: [Select]

void LED_Flash()        // LED aufblitzen lassen
{
  static boolean state_LED = LOW;
  static unsigned long millis_LED = 0;
                
     if (state_LED == LOW && millis() > millis_LED )  {
       digitalWrite(Flash_LED, HIGH);        // LED einschalten für
       millis_LED = millis() + 50;           // für 50ms
       state_LED = HIGH;
     }
     if (state_LED == HIGH && millis() > millis_LED )  {
       digitalWrite(Flash_LED, LOW);         // LED ausschalten für
       millis_LED = millis() + 2000;         // für 2 sec.
       state_LED = LOW;
     }  
}
Tschau
Doc Arduino '\0'

Messschieber auslesen: http://forum.arduino.cc/index.php?topic=273445
EA-DOGM Display - Demos: http://forum.arduino.cc/index.php?topic=378279

michael_x

Doc,

deine BlinkWithoutDelay - Version hat den Vorteil, dass sie zeigt, wie man 2 Zeiten realisiert,
aber den kleinen Nachteil, dass die minimale Chance besteht, dass sie nach ca. 50 Tagen hängen bleibt.

Falls millis_LED mal auf 0xFFFFFFFF gesetzt wird, ist der Vergleich nie mehr erfüllt.
Wenn LED_Flash() nicht jede msec dran kommt, wird die "Gefahr" noch etwas größer.
Andererseits funktioniert die Differenz-Bildung selbst während des Überlaufs von millis() richtig!

Besser als den nächsten Schaltpunkt zu merken ist, den vorigen zu merken.

Code: [Select]
const int Flash_LED=13;  // LED Pin
void LED_Flash()        // LED aufblitzen lassen
{
  const int OFFTIME=2000; // alle 2 sec
  const int ONTIME=50;   // für 50 msec blitzen lassen

  static boolean state_LED;  // aktueller Zustand
  static unsigned long millis_LED;  // letzter Schaltzeitpunkt

                 
     if (state_LED == LOW && millis() - millis_LED > OFFTIME)  {
       digitalWrite(Flash_LED, HIGH);        // nach 2 sec: LED einschalten
       millis_LED = millis();
       state_LED = HIGH;
     }
     if (state_LED == HIGH && millis() - millis_LED > ONTIME )  {
       digitalWrite(Flash_LED, LOW);         // nach 50 msec: LED ausschalten
       millis_LED = millis(); 
       state_LED = LOW;
     }   
}


Ich hoffe, das leicht modifizierte Beipiel ist fast genauso leicht zu verstehen wie Doc's Original-Beispiel.

Die Rangfolge Multiplikation vor Addition vor Vergleich vor Logik erlaubt das Weglassen der inneren Klammern bei
Code: [Select]
if ( (state_LED == LOW) && ((millis() - millis_LED) > OFFTIME) )

Aber wenn das einem zum Verständnis hilft, kann man sie natürlich auch setzen.

benelli92

Super, vielen Dank euch allen :)

Go Up