Als mein erstes Arduino Projekt habe ich mir den Bau eines Intervalometers für meine DSLR vorgenommen. Die erste Version funktioniert soweit auch ganz gut. Der Intervall wird mit drei Codierschaltern eingestellt (Das soll sich auch noch ändern, da dadurch nur 8 Intervalle möglich sind... Vielleicht wird irgendwann mal ein LCD Bildschirm zur freien Einstellung des Intervalls mit Tasten eingebaut) Die Intervallaufnahme lässt/ließ sich durch einen Taster starten, welcher aber oft prelllt, dadurch wird das Ganze sofort wieder gestoppt. Ich habe versucht den Taster so wie es in der Referrenz (http://www.arduino.cc/en/Tutorial/Debounce) steht zu entprellen, aber jetzt funktioniert garnichts mehr ...
Hier das Sketsch:
#include <MsTimer2.h>
// Kameraausloeser
#define kameraPin 13
// Laenge des Ausloesesignals
#define ausloeseZeit 500
// Codierschalter Eingänge
const int schalter1Pin = 2;
const int schalter2Pin = 3;
const int schalter3Pin = 4;
// Variablen für Codierung
int schalter1State;
int schalter2State;
int schalter3State;
// Intervall-Variable
long intervall;
// Pin's für Start & Stopp
int on_offPin = 8;
int on_offval;
int on_offState;
int on_off = 0;
// Codierung
boolean codierung = false;
unsigned long last_tm = 0;
boolean belichten = false;
long lastDebounceTime = 0; // the last time the output pin was toggled
long debounceDelay = 50; // the debounce time; increase if the output flickers
void setup(){
// Pin's definieren
pinMode(schalter1Pin, INPUT);
pinMode(schalter2Pin, INPUT);
pinMode(schalter3Pin, INPUT);
pinMode(kameraPin, OUTPUT);
// Debugging
Serial.begin(9600);
// Grundwert beim Einschalten
on_offState = digitalRead(on_offPin);
}
void loop() {
// Zustand des Startknopfes speichern
on_offval = digitalRead(on_offPin);
// Start-Taste gedrückt?
if(on_offval != on_offState){ // Weicht der Zustand des Knopfes vom Grundwert beim Einschalten ab?
lastDebounceTime = millis(); // aus der Refernz übernommen
if(on_offval == LOW){ // Wenn ja, und er LOW ist und...
if ((millis() - lastDebounceTime) > debounceDelay) { // aus der Refernz übernommen
if(on_off == 0){ // ...nicht schon eingeschaltet wurde, dann...
on_off = 1; // ...Modus auf "ein" setzen!
Serial.println("an!");
}
else{
on_off = 0; // Sonst Modus auf "aus" setzen!
codierung = false; // Codierung zurücksetzen
Serial.println("aus!");
}
}
}
}
// Zustand des Knopfes während des Starts der Aufnahmesequenz mit dem Grundwert gleichsetzen
on_offState = on_offval;
// Wenn der Einschaltknopf gedrückt wurde...
if(on_off == 1){
// ...und die Codierung noch nicht vorgenommen wurde:
if (codierung == false){
intervall_bestimmung();
}
if(belichten == false && millis() - last_tm > intervall){
MsTimer2::set(ausloeseZeit, camera_off);
MsTimer2::start();
// Intervall für Debugging ausgeben
Serial.println(intervall);
belichten = true;
digitalWrite(kameraPin, HIGH);
}
}
}
void camera_off(){
digitalWrite(kameraPin, LOW);
MsTimer2::stop();
last_tm = millis();
belichten = false;
}
void intervall_bestimmung(){
// Codierung auslesen
schalter1State = digitalRead(schalter1Pin);
schalter2State = digitalRead(schalter2Pin);
schalter3State = digitalRead(schalter3Pin);
// Codierung ausgeben für Debugging
Serial.println(schalter1State);
Serial.println(schalter2State);
Serial.println(schalter3State);
//Intervall ermitteln
if(schalter1State == HIGH){
if(schalter2State == HIGH){
if(schalter3State == HIGH){ //HHH
intervall = 1000;
}
if(schalter3State == LOW){ //HHL
intervall = 2000;
}
}
if(schalter2State == LOW){
if(schalter3State == HIGH){ //HLH
intervall = 3000;
}
if(schalter3State == LOW){ //HLL
intervall = 5000;
}
}
}
else if(schalter1State == LOW){
if(schalter2State == HIGH){
if(schalter3State == HIGH){ //LHH
intervall = 8000;
}
if(schalter3State == LOW){ //LHL
intervall = 10000;
}
}
if(schalter2State == LOW){
if(schalter3State == HIGH){ //LLH
intervall = 15000;
}
if(schalter3State == LOW){ //LLL
intervall = 20000;
}
}
}
// Codierung auf wahr setzen
codierung = true;
}
Was mache ich falsch? Habe schon viele andere Anleitungen für Debouncing angeschaut, hat aber allles nicht funktioniert oder war zu kompliziert für mich
Könnt ihr mir vielleicht einen Tipp geben? Ich bin natürlich immer für Verbesserungsvorschläge am Script offen
wäre es nicht einfacher 3 schalter zu nehmen?
die dann beim initialisieren auslesen und dann je nach stellung (da sind ja acht möglich) den auslösetimer zu setzen.
dann wenn du was ändern willst, einfach schalter umstellen und reset drücken. schon läufts mit der neuen einstellung.
da die schalter ja dann auch stehen sollte es mit dem entprellen keine probleme geben.
also so in der art:
int long TIMER = 500; // Basisverzoegerung
void setup() {
//Start Serielles Interface
Serial.begin(9600);
// Camera Pin
pinMode(13, OUTPUT);
// Schalter
pinMode(2, INPUT);
pinMode(3, INPUT);
pinMode(4, INPUT);
// interne Pullup Widerstände aktivieren
digitalWrite(2, HIGH);
digitalWrite(3, HIGH);
digitalWrite(4, HIGH);
// Schalterstellung lesen (Schalter schliessen auf Masse)
if ( digitalRead(2) == HIGH ) { TIMER = TIMER + 500; } // Zusatz-Verzoegerung Schalter 2
if ( digitalRead(3) == HIGH ) { TIMER = TIMER + 1000; } // Zusatz-Verzoegerung Schalter 3
if ( digitalRead(4) == HIGH ) { TIMER = TIMER + 2000; } // Zusatz-Verzoegerung Schalter 4
// Ausgabe was nun eingestellt wurde
/*
5 4 3 - Arduino-Pin
L L L = 500 ms
L L H = 1000 ms
L H L = 1500 ms
L H H = 2000 ms
H L L = 2500 ms
H L H = 3000 ms
H H L = 3500 ms
H H H = 4000 ms
*/
Serial.print("Auslese-Verzoegerung = "); Serial.print(TIMER/1000); Serial.println(" sek.");
}
void loop() {
Serial.println("Klick");
// Bild machen
digitalWrite(13, HIGH);
delay(250);
digitalWrite(13, LOW);
delay(TIMER-250); //das ausloesen abziehen und warten bis zum naechsten bild
}
Die Werte der einzelnen Schalter kannst einfach abändern, da ich nicht genau weis welche Werte Du da möchtest.
Alternativ kannst auch komplett freie Werte für die einzelnen Schalterstellungen einstellen mit z.B. sowas:
if ( digitalRead(2) == LOW && digitalRead(3) == LOW && digitalRead(4) == LOW ) { TIMER = 5; } // 5 Sekunden
if ( digitalRead(2) == HIGH && digitalRead(3) == LOW && digitalRead(4) == LOW ) { TIMER = 30; } // 30 Sekunden
if ( digitalRead(2) == LOW && digitalRead(3) == HIGH && digitalRead(4) == LOW ) { TIMER = 60; } // 1 Minute
if ( digitalRead(2) == HIGH && digitalRead(3) == HIGH && digitalRead(4) == LOW ) { TIMER = 90; } // 1,5 Minuten
if ( digitalRead(2) == LOW && digitalRead(3) == LOW && digitalRead(4) == HIGH ) { TIMER = 300; } // 5 Minuten
if ( digitalRead(2) == HIGH && digitalRead(3) == LOW && digitalRead(4) == HIGH ) { TIMER = 1800; } // 1/2 Stunde
if ( digitalRead(2) == LOW && digitalRead(3) == HIGH && digitalRead(4) == HIGH ) { TIMER = 3600; } // 1 Stunde
if ( digitalRead(2) == HIGH && digitalRead(3) == HIGH && digitalRead(4) == HIGH ) { TIMER = 86400; } // 1 Tag
TIMER=TIMER*1000; // Umrechnung der Sekunden in Millisekunden für den delay-Befehl
vielen Dank für deine ausführliche Antwort. Dadurch ist mir einiges klar geworden (Endlich die Sache mit den intigrierten Pullup Wiederständen kapiert ;)) Leider besteht mein eigentliches Problem immernoch: Debouncing. Ich möchte in das Intervalometer einen Startknopf, der die aufnahmesequenz startet, einbauen. Dieser ist an Pin 8 des UNO angeschlossen und funktioniert soweit auch, nur ich bekomme es nicht hin wie es in der Referenz steht zu entprellen
In diesem Abschnitt ist das Problem:
// Start-Taste gedrückt?
if(on_offval != on_offState){ // Weicht der Zustand des Knopfes vom Grundwert beim Einschalten ab?
lastDebounceTime = millis(); // aus der Refernz übernommen
if(on_offval == LOW){ // Wenn ja, und er LOW ist und...
if ((millis() - lastDebounceTime) > debounceDelay) { // aus der Refernz übernommen
if(on_off == 0){ // ...nicht schon eingeschaltet wurde, dann...
on_off = 1; // ...Modus auf "ein" setzen!
Serial.println("an!");
}
else{
on_off = 0; // Sonst Modus auf "aus" setzen!
codierung = false; // Codierung zurücksetzen
Serial.println("aus!");
}
}
}
}
Wenn ich die Sachen an denen "aus der Referenz übernommen" steht zum Entprelllen in das Sketch einfüge, funktioniert der Startknopf garnicht mehr...
void blaaa() {
static unsigned long lastDebounce = 0;
if (lastDebounce == 0) {
//wir schaun, ob wir bereits im debounce sind. wenn nicht, schaun wir, ob der button sich geändert hat
on_offval = digitalRead(BUTTON_PIN);
if (on_offval != on_offState) {
//button geändert, wir starten den debounce
lastDebounce = millis();
}
} else if (millis() > lastDebounce + 50) {
//wir sind jetzt bereits im debounce und die wartezeit ist vergangen. wir testen nochmal den pin und übernehmen den jetzigen zustand als wert
lastDebounce = 0; //wichtig, wir müssen resetten, damit der debounce das nächste mal wieder gestartet werden kann.
on_offval = digitalRead(BUTTON_PIN);
if (on_offval == on_offState) {
//da hat sich nix geändert, also muss auch nix ausgeführt werden
return;
}
on_offState = on_offval;
//tu hier, was mit dem neuen state getan werden soll (if on_offState = low u.s.w.)
}
}
keine Gewähr, dass das sofort so kompiliert, oder funktioniert. Ich kann das halt nicht testen. Aber es geht ja auch primär um die Idee dahinter.