Aktualisiert
This commit is contained in:
parent
6540b2f2f0
commit
f2a56d66a3
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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();
|
||||
};
|
||||
|
|
@ -3,15 +3,15 @@
|
|||
* See the README for detailed documentation.
|
||||
*/
|
||||
|
||||
#include <RotaryDialer.h>
|
||||
#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();
|
||||
}
|
||||
|
Loading…
Reference in New Issue