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?
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)
Taster einlesen
Positive Flanke und Programm nicht aktiv -> Programm ausführen
Negative Flanke -> Programm beenden
Gedrückthalten des Tasters hat dann keinen Effekt auf ein erneutes Programm starten. Der Taster muss erneut gedrückt werden.
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.
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?
sorry für den Doppelpost.
Bin grad echt am verzweifeln
Weiss denn niemand, warum der loop immer genau doppelt durchlaufen wird? ich kann es mir echt nicht erklären.
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...
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...
#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
}
}
}
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.
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.
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.
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;
}
}
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.
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.