From f2a56d66a3167ca2ca922c133295a774bbec0058 Mon Sep 17 00:00:00 2001 From: starcalc Date: Thu, 26 Apr 2018 23:10:18 +0200 Subject: [PATCH] Aktualisiert --- examples/dialtoserial/RotaryDialer.cpp | 108 ++++++++++++++++++ examples/dialtoserial/RotaryDialer.h | 71 ++++++++++++ .../{dialtoserial.pde => dialtoserial.ino} | 8 +- 3 files changed, 183 insertions(+), 4 deletions(-) create mode 100644 examples/dialtoserial/RotaryDialer.cpp create mode 100644 examples/dialtoserial/RotaryDialer.h rename examples/dialtoserial/{dialtoserial.pde => dialtoserial.ino} (75%) diff --git a/examples/dialtoserial/RotaryDialer.cpp b/examples/dialtoserial/RotaryDialer.cpp new file mode 100644 index 0000000..fd48553 --- /dev/null +++ b/examples/dialtoserial/RotaryDialer.cpp @@ -0,0 +1,108 @@ +#include "RotaryDialer.h" + +#if defined(ARDUINO) && ARDUINO >= 100 +#include "Arduino.h" +#else +#include "WProgram.h" +#endif + +#define NO_NUMBER -1 + +// Require DEBOUNCE_DELAY milliseconds between state changes. This value is +// noted in the class documentation. +#define DEBOUNCE_DELAY 15 + +RotaryDialer::RotaryDialer(int readyPin, int pulsePin) : + pinReady(readyPin), pinPulse(pulsePin), hasCompletedNumber(false), + state(WAITING) +{ } + +void RotaryDialer::setup() { + pinMode(pinReady, INPUT); + pinMode(pinPulse, INPUT); + digitalWrite(pinReady, HIGH); + digitalWrite(pinPulse, HIGH); + lastStateChangeMillis = millis(); +} + +bool RotaryDialer::changeStateIfDebounced(enum State newState) { + unsigned long currentMillis = millis(); + if (currentMillis < lastStateChangeMillis) { + // clock wrapped; ignore (but could figure it out in this case) + lastStateChangeMillis = currentMillis; + return false; + } else if (currentMillis - lastStateChangeMillis > DEBOUNCE_DELAY) { + state = newState; + lastStateChangeMillis = currentMillis; + return true; + } else { + return false; + } +} + +void RotaryDialer::completeDial() { + if (!changeStateIfDebounced(WAITING)) { + return; + } + if (number > 0 && number <= 10) { + if (number == 10) { + number = 0; + } + hasCompletedNumber = true; + } +} + +bool RotaryDialer::update() { + int readyStatus = digitalRead(pinReady); + int pulseStatus = digitalRead(pinPulse); + if ((readyStatus == 0) && (pulseStatus==1)) + { + //Serial.print("Ready: "); + //Serial.print(readyStatus); + //Serial.print(" Pulse: "); + //Serial.print(pulseStatus); + //Serial.print(" State: "); + //Serial.println(state); + } + switch(state) { + case WAITING: + if (readyStatus == LOW + && changeStateIfDebounced(LISTENING_NOPULSE)) + { + hasCompletedNumber = false; + number = 0; + } + break; + case LISTENING_NOPULSE: + if (readyStatus == HIGH) { + completeDial(); + } else if (pulseStatus == HIGH) { + changeStateIfDebounced(LISTENING_PULSE); + } + break; + case LISTENING_PULSE: + if (readyStatus == HIGH) { + completeDial(); + } else if (pulseStatus == LOW + && changeStateIfDebounced(LISTENING_NOPULSE)) + { + number++; + } + break; + } + return hasCompletedNumber; +} + +bool RotaryDialer::hasNextNumber() { + return hasCompletedNumber; +} + +int RotaryDialer::getNextNumber() { + if (hasCompletedNumber) { + hasCompletedNumber = false; + return number; + } else { + return NO_NUMBER; + } +} + diff --git a/examples/dialtoserial/RotaryDialer.h b/examples/dialtoserial/RotaryDialer.h new file mode 100644 index 0000000..db18076 --- /dev/null +++ b/examples/dialtoserial/RotaryDialer.h @@ -0,0 +1,71 @@ +#pragma once + +/** + * Read numbers from a rotary dial (or otherwise using pulse dialing; see + * http://en.wikipedia.org/wiki/Rotary_dial ). + * + * See the README for further documentation. + */ +class RotaryDialer { + private: + int pinReady; + int pinPulse; + bool hasCompletedNumber; + int number; + + enum State { + WAITING, + LISTENING_NOPULSE, + LISTENING_PULSE + }; + enum State state; + unsigned long lastStateChangeMillis; + + /** + * Change state, but only if enough time has elapsed since + * the last state change (to protect from noise). + */ + bool changeStateIfDebounced(enum State newState); + + /** + * To be called when ready returns HIGH (when the rotor returns + * to its rest position); save the number, if valid. + */ + void completeDial(); + public: + /** + * Create a new RotaryDialer listening on the given pins. + * @param readyPin connected to a NO (HIGH) switch on the rotor + * which is closed (LOW) during dialing + * @param pulsePin connected to a NC (LOW) switch on the rotor + * which is opened (HIGH) during each pulse + */ + RotaryDialer(int readyPin, int pulsePin); + + /** + * Initialize the pins; digital read pins, held HIGH. + */ + void setup(); + + /** + * Check the pins and update state (in or out of a pulse, + * dialing complete, etc). This must be called at least as + * pulses; assuming 10 pulses per second, every 50ms. + */ + bool update(); + + /** + * @return whether a new number has been dialed since the last + * getNextNumber call + */ + bool hasNextNumber(); + + /** + * Get the most recently dialed number. After this is called, + * hasNextNumber will return false until a new number is dialed. + * @return the most recently dialed number, and clear + * hasNextNumber + */ + int getNextNumber(); +}; + diff --git a/examples/dialtoserial/dialtoserial.pde b/examples/dialtoserial/dialtoserial.ino similarity index 75% rename from examples/dialtoserial/dialtoserial.pde rename to examples/dialtoserial/dialtoserial.ino index bcdea9c..963f510 100644 --- a/examples/dialtoserial/dialtoserial.pde +++ b/examples/dialtoserial/dialtoserial.ino @@ -3,15 +3,15 @@ * See the README for detailed documentation. */ -#include +#include "RotaryDialer.h" -#define PIN_READY 8 -#define PIN_PULSE 9 +#define PIN_READY D6 +#define PIN_PULSE D5 RotaryDialer dialer = RotaryDialer(PIN_READY, PIN_PULSE); void setup() { - Serial.begin(28800); + Serial.begin(115200); dialer.setup(); }