Tastendruck Zeit messen - erledigt! - oder doch nicht?!

Hallo Allerseits!

ich suche eine Lösung, wie ich die Dauer eines Zustandes abfragen kann. Auf der Suche im Web bzw. im Arduino Kochbuch hab ich folgendes gefunden, was beim durchlesen der Beschreibung keine meiner Anwendung entsprechen würde:

/*
  millisDuration Sketch
  Gibt an, wie lange (in Millisekunden) eine Taste gedrückt wude
 */

const int switchPin = 16;                   // Eingangspin

long startTime; // millis-Wert beim ersten Drücken der Taste
long duration;  // Variable für die Dauer

void setup()
{
  pinMode(switchPin, INPUT);
  digitalWrite(switchPin, HIGH); // Pullup-Widerstand aktivieren
  Serial.begin(9600);
}


void loop()
{
  if(digitalRead(switchPin) == LOW)
  {
     // Sobald die Taste gedrückt wurde
     startTime = millis();
     while(digitalRead(switchPin) == LOW)
        ; // Warten, solange die Taste gedrückt wird
     long duration = millis() - startTime;
     Serial.println(duration);
  }
}

Nun leider wird mir hier nicht die Dauer des gedrückten Tasters angezeigt, sondern die Zeit, welche seit dem letzten mal drücken vergangen ist.

wo muß ich ansetzen um das zu bekommen was ich brauche?

besten Dank für eure hilfe schon mal im voraus.

schönen Gruß
Bernhard

Hat sich soeben erledigt, musste lediglich Pulldown anstatt Pullup Widerstand am Eingang schalten, und digitalRead auf HIGH setzen...

trotzdem Danke!

Bitte.
Schön Dir geholfen zu haben. Einen Beitrag schreiben läßt darüber nachdenken und manchnmal die Lösung selbst finden :wink: :wink: :wink: :wink: :wink:
Grüße Uwe

Wenn du den Taster mit GND verbunden hättest, wäre das mit den Pullup und LOW richtig gewesen :wink:
Auch wenn anfangs etwas ungewohnt, hat Pullup eher Vorteile ( nicht nur weil der Widerstand schon im Controller vorhanden ist )

Auch glaube ich nicht, dass du mit negativen Werten für duration rechnest, aber unsigned ist tatsächlich so schwierig zu schreiben, dass es jeder vermeidet, wenn möglich.

Du könntest übrigens auch eine der beiden Definitionen von duration weglassen, da die erste bei dir nie verwendet wird...

Aber da dein Programm jetzt (mit dem Pulldown-Widerstand) geht, ist es gut: Herzlichen Glückwunsch!
Nur falls es jemand findet und nachbaut, und weil ich schon länger nicht mehr gemeckert habe, wollte ich es mal wieder gesagt haben ...

hi,

Bitte.
Schön Dir geholfen zu haben. Einen Beitrag schreiben läßt darüber nachdenken und manchnmal die Lösung selbst finden

auch eine art von rubberducking. Rubber duck debugging - Wikipedia

nur falls sich jemand fragt, warum IBM gern kleine gummienten an programmierer von kunden verteilt.

gruß stefan

Schön, dass ein für mich erledigter Beitrag noch so schön Kommentiert wird - DANKE! wärend ein anderer in der Versenkung untergeht... Dann probier ichs hier noch mal.

Ich möchte die Zeit, zwischen 2 Temperaturen messen. Der Stand ist so, dass die Stopuhr zwar gestartet wird, aber bei jedem Loop erneut gestartet wird. Der Code sieht folgendermassen aus.

//Stopuhr über interne mills-funktion
//Start und Stop über einen gemeinsamen Taster an Pin 6
//Reset bzw. Zurückstellen mit Taster an analogpin 2 Pin 16
//Anzeige: s,tsd

//Start und Stop über Temperaturschwellwerte ausgelöst

#include <LiquidCrystal.h> //Display
#include <Wire.h>
#include <OneWire.h>
#include <DallasTemperature.h>


const int StartPin = 6;
const int ResetPin = 16;
const int LedAktiv =  7;

#define ONE_WIRE_BUS 15 // Data wire is plugged into pin A1 Analog Input als Digital Input
OneWire oneWire(ONE_WIRE_BUS); // Setup a oneWire instance to communicate with any OneWire devices
DallasTemperature sensors(&oneWire); // Pass our oneWire reference to Dallas Temperature. 
DeviceAddress insideThermometer = { 0x10, 0x89, 0x14, 0x90, 0x02, 0x08, 0x00, 0x3C }; //Adresse des Temperatursensors

const String INITIAL_MESSAGE = "START druecken  ";
const String TIMING_MESSAGE = "Zeit: ";
const String EINHEIT_MESSAGE = " Sek.";
const String AKTIV_MESSAGE = "Messung aktiv";

int buttonVal = 0;
int buttonOldVal = 0;
int buttonState = 0;
int ResetState = 0;
int TempVal = 0;
int TempOldVal = 0;
int TempState = 0;

long startTime = 0;
float endTime = 0;
boolean showTimer = false;


LiquidCrystal lcd(8,9,5,4,3,2);

void setup(){
  
  lcd.begin(16, 2);
  lcd.print(INITIAL_MESSAGE);
  
  pinMode(StartPin, INPUT);
  pinMode(ResetPin, INPUT);
  pinMode(LedAktiv, OUTPUT);
  
  Serial.begin(9600);
  
}

void loop(){
  sensors.requestTemperatures(); //Temperatur aktualisieren bzw. abfragen
float tempC = sensors.getTempC(insideThermometer);
Serial.print(tempC); // Nur zum Überprüfen - später nicht im Programm
Serial.print(" Time"); // Nur zum Überprüfen - später nicht im Programm
Serial.print(" "); // Nur zum Überprüfen - später nicht im Programm
Serial.print(millis()); // Nur zum Überprüfen - später nicht im Programm
Serial.print("\n"); // Nur zum Überprüfen - später nicht im Programm


// --- Start Stopuhr mittels Temp --- //

if(tempC <= 40.00 && tempC >= 30.00){
startTimer();
LedStatus_aktiv();
} else {
endTimer();
LedStatus_passiv();
}

// --- Start Stopuhr mittels Taster --- //
//buttonVal = digitalRead(StartPin);
//delay(10);
//if(buttonVal == HIGH && buttonOldVal == LOW){
//buttonState = 1 - buttonState;
//if(buttonState == 1){
//startTimer();
//LedStatus_aktiv();
//} else {
//endTimer();
//LedStatus_passiv();
//}
   
//}
 
 if(showTimer == true){
   printTime();
 }

// buttonOldVal = buttonVal;
 
 ResetState = digitalRead(ResetPin);
 if (ResetState == HIGH && buttonState == 0) {
   resetTime();
 } else {
   if (ResetState == HIGH && buttonState == 1){
     lcd.clear();
     lcd.print(AKTIV_MESSAGE);
   }
 }
  
  lcd.setCursor(0, 1);
  lcd.print("Temp. ");
  printTemperatureLCD(insideThermometer);
  lcd.write(223); //schreibt °
  lcd.write("C");
}

void startTimer(){
 
 showTimer = true;
 startTime = millis();
 lcd.clear();
 lcd.print(TIMING_MESSAGE);
  
}

void endTimer(){
  
 showTimer = false;
 lcd.setCursor(0,0);
 lcd.print(TIMING_MESSAGE);
 lcd.print(endTime / 1000,2);
 lcd.print(EINHEIT_MESSAGE);
 
}

void printTime(){
  
  float timeVal = endTime = millis() - startTime;
  lcd.setCursor(0,0);
  lcd.print(TIMING_MESSAGE);
  lcd.print(timeVal / 1000,2);
  lcd.print(EINHEIT_MESSAGE);
  
  
}

void resetTime(){
//  digitalWrite(ledPin, HIGH);
  lcd.setCursor(0,0);
  lcd.print(INITIAL_MESSAGE);
}

void LedStatus_aktiv(){
  digitalWrite(LedAktiv, HIGH);
} 
void LedStatus_passiv(){
  digitalWrite(LedAktiv, LOW);
} 

void printTemperatureLCD(DeviceAddress deviceAddress)
{
  float tempC = sensors.getTempC(deviceAddress);
  if (tempC == -127.00) {
    lcd.print("Error getting temperature");
  } else {
    lcd.print(tempC,2);//auf LCD schreiben mit 2 Nachkommastelle und kaufmänisch gerundet
  }
}

eine genauere Beschreibung des Projektes hab ich auch hier im Forum:
http://forum.arduino.cc/index.php?topic=183093.msg1356369#msg1356369

Die Funktionen für die Tasten sind im Sketch mit // Kommentiert, diese Funktionen benötige ich dann für etwas anderes (SD-Logger START/STOP)

michael_x:
Auch wenn anfangs etwas ungewohnt, hat Pullup eher Vorteile ( nicht nur weil der Widerstand schon im Controller vorhanden ist )

Äh- welche denn? Der Stromverbrauch soll ja z.B. schon einmal höher sein als bei einer Pulldown-Schaltung.

Gruß Chris

Kannst du nicht einfach eine bool Variable nehmen mit der du speicherst ob die Stopuhr läuft? Und dann startTimer() nur aufrufen wenn sie false ist. Die wird dann in startTimer() auf true gesetzt und in endTimer() auf false.

Chris72622:

michael_x:
Auch wenn anfangs etwas ungewohnt, hat Pullup eher Vorteile ( nicht nur weil der Widerstand schon im Controller vorhanden ist )

Äh- welche denn? Der Stromverbrauch soll ja z.B. schon einmal höher sein als bei einer Pulldown-Schaltung.

Gruß Chris

Ich schließe mich Chris an, mir persönlich ist Pulldown wesentlich geläufiger. Vorteile bei Pullup sind mir kaum bekannt.

Serenifly:
Kannst du nicht einfach eine bool Variable nehmen mit der du speicherst ob die Stopuhr läuft? Und dann startTimer() nur aufrufen wenn sie false ist. Die wird dann in startTimer() auf true gesetzt und in endTimer() auf false.

Okay, diese Funktion kenn ich (noch) nicht. Muß ich mal gucken wie das genau läuft bzw. wie ich das in meiner Anwendung löse. Danke für den Hinweis.

Gruß
Bernhard

Was heißt du kennst das nicht? Du hast das doch schon genauso mit "boolean showTimer". Wenn ich mir dass so ansehe brauchst du gar keine neue Variable sondern kannst gleich showTimer dafür ebenfalls verwenden. Das könnte man dann in "timerRunning" umbenennen damit die Funktion klarer ist.

Chris72622:

michael_x:
Auch wenn anfangs etwas ungewohnt, hat Pullup eher Vorteile ( nicht nur weil der Widerstand schon im Controller vorhanden ist )

Äh- welche denn? Der Stromverbrauch soll ja z.B. schon einmal höher sein als bei einer Pulldown-Schaltung.

Gruß Chris

Generell stimme ich zu: "Taste gedrückt und Kontakt geschlossen == 1 == HIGH" ist erstmal intuitiver.

Der Strom hängt wohl mehr von der Größe des Widerstands ab als von Up/Down, und sollte eigentlich bei offenem Taster praktisch 0, bei gedrücktem Taster immerhin vernachlässigbar sein. Der bei Wikipedia erwähnte Nachteil gilt eher "compared to an active current source".

Bei TTL Logic ist das mit dem Stromverbrauch eher umgekehrt (s. hier).

OpenCollector - Schaltungen brauchen immer einen Pullup. ( Beispiel I²C )

Lt. Udo Klein: Pullup hat geringfügig höhere Sicherheit gegen Noise

Per Definition ist GND immer GND, während es für Vcc schon eher mal verschiedene Level gibt. Den Taster mit GND zu verbinden, ist daher etwas sicherer gegen Fehlverdrahtungen auf dem Steckbrett :wink:

Der in den atmega und attiny fertig eingebaute PullUp ist sicher das wichtigste, was dafür spricht, ihn auch zu verwenden.

Pullup und Pulldown gleichzeitig ist ganz schlecht.

OT:
pulldowns are generally easier for a beginner :wink:

Pullups haben den Vorteil, daß man alle Schalter immer gegen Masse schalten kann. Bei Pulldowns muß man für jeden Schalter wissen was das richtige Bezugspotential ist. Von daher kann man mit Pullups weniger Fehler machen. Auf Englisch würde ich sagen: Pulldows are genereally less prone to mistake and thus better suited for beginners :wink: