Rotary Encoder旋转编码器
1 #define PIN_HIGHBIT (7) 2 #define PIN_LOWBIT (5) 3 #define PIN_PWR (3) 4 #define BAUDRATE (9600) 5 #define DEBUG (1) 6 7 // globals 8 int state, prevState = 0, count = 0; 9 /* old state, new state, change (+ means clockwise) 10 * 0 2 + 11 * 1 0 + 12 * 2 3 + 13 * 3 1 + 14 * 0 1 - 15 * 1 3 - 16 * 2 0 - 17 * 3 2 - 18 */ 19 int encoderStates[4][4] = { 20 { 0, -1, 1, 0 }, 21 { 1, 0, 0, -1 }, 22 { -1, 0, 0, 1 }, 23 { 0, 1, -1, 0 }, 24 }; 25 26 void setup() { 27 pinMode(PIN_HIGHBIT, INPUT); 28 pinMode(PIN_LOWBIT, INPUT); 29 pinMode(PIN_PWR, OUTPUT); 30 digitalWrite(PIN_PWR, LOW); 31 digitalWrite(PIN_LOWBIT, HIGH); 32 digitalWrite(PIN_HIGHBIT, HIGH); 33 Serial.begin(BAUDRATE); 34 } 35 36 void loop() { 37 state = (digitalRead(PIN_HIGHBIT) << 1) | digitalRead(PIN_LOWBIT); 38 count += encoderStates[prevState][state]; 39 40 #ifdef DEBUG 41 if (state != prevState) { 42 Serial.print(state, DEC); 43 Serial.print(' '); 44 Serial.print(prevState, DEC); 45 Serial.print(' '); 46 Serial.println(count, DEC); 47 } 48 #endif 49 50 prevState = state; 51 }
/* Rotary_Encoder_LED_Ring_Example www.mayhewlabs.com/products/rotary-encoder-led-ring Copyright (c) 2011 Mayhew Labs. Written by Mark Mayhew This example shows 3 sequences that are possible on the ring of LEDs around the encoder based on rotation of an encoder. The 3 sequences are selected by entering 1, 2, or 3 in the serial command prompt. The serial window shows the current rotary encoder count. As the encoder is turned, the serial display shows a raw count of the rotary encoder's value and the LEDs show a scaled version of the value. If the button on the rotary encoder is pushed, the bottom LED will come on. Each section of code below discusses the process required to do this. A note on setting the output sequence: Think of each LED as a single bit in a 16-bit long binary string. If a bit is 1, the LED is on, if a bit is 0, the LED is off. By making a string of ones and zeros, we choose which LEDs to have on and off, and then send this string to the shift register to display it. For example 1000000000000001 binary (0x8001 in hex) will have the fist and last LEDs on, the rest off. CREDIT: Reading the rotary encoder is performed with Oleg's example code:a http://www.circuitsathome.com/mcu/reading-rotary-encoder-on-arduino */ //These are the pins that will talk to the shift register through SPI #define SDI 2 //Data #define CLK 3 //Clock #define LE 4 //Latch //These are the rotary encoder pins A, B, and switch #define ENC_A 8 #define ENC_B 9 #define ENC_SW 10 #define ENC_PORT PINB //The port that the rotary encoder is on (see http://www.arduino.cc/en/Reference/PortManipulation) // Global variables int scaledCounter = 0; //The LED output is based on a scaled veryson of the rotary encoder counter int sequenceNumber=0; //The output sequence for the LEDs int incomingByte = 0; //Serial input to select LED output sequence /*This is a 2 dimensional array with 3 LED sequences. The outer array is the sequence; the inner arrays are the values to output at each step of each sequence. The output values are 16 bit hex values (hex math is actually easier here!). An LED will be on if its corresponding binary bit is a one, for example: 0x7 = 0000000000000111 and the first 3 LEDs will be on. The data type must be 'unsigned int' if the sequence uses the bottom LED since it's value is 0x8000 (out of range for signed int). */ unsigned int sequence[3][16] = {{0x0,0x1,0x2,0x4,0x8,0x10,0x20,0x40,0x80,0x100,0x200,0x400,0x800,0x1000,0x2000,0x4000}, {0x0,0x1,0x3,0x7,0xf,0x1f,0x3f,0x7f,0xff,0x1ff,0x3ff,0x7ff,0xfff,0x1fff,0x3fff,0x7fff}, {0x0,0x7fff,0x3ffe,0x1ffc,0xff8,0x7f0,0x3e0,0x1c0,0x80,0x1c0,0x3e0,0x7f0,0xff8,0x1ffC,0x3ffe,0x7fff}, }; void setup() { //Set SPI pins to output pinMode(SDI, OUTPUT); pinMode(CLK, OUTPUT); pinMode(LE,OUTPUT); //Set encoder pins to input, turn internal pull-ups on pinMode(ENC_A, INPUT); digitalWrite(ENC_A, HIGH); pinMode(ENC_B, INPUT); digitalWrite(ENC_B, HIGH); pinMode(ENC_SW, INPUT); digitalWrite(ENC_SW, HIGH); //Set serial rate, prompt for desired sequence Serial.begin(115200); Serial.println("Enter 1, 2, or 3 to change the LED sequence"); } void loop() { //Local Variables static uint8_t counter = 0; //this variable will be changed by encoder input int8_t tmpdata; //Get any serial input if (Serial.available() > 0) { incomingByte = Serial.read(); } //if the serial input is valid, set the LED output sequence appropriately if (incomingByte == '1') sequenceNumber=0; if (incomingByte == '2') sequenceNumber=1; if (incomingByte == '3') sequenceNumber=2; //Call read_encoder() function tmpdata = read_encoder(); //if the encoder has moved if(tmpdata) { //Print out the counter value Serial.print("Counter value: "); Serial.println(counter, DEC); //Set the new counter value of the encoder counter += tmpdata; //Scale the counter value for referencing the LED sequence //***NOTE: Change the map() function to suit the limits of your rotary encoder application. // The first two numbers are the lower, upper limit of the rotary encoder, the // second two numbers 0 and 14 are limits of LED sequence arrays. This is done // so that the LEDs can use a different scaling than the encoder value. scaledCounter = map(counter,0,100,0,15); //Send the LED output to the shift register digitalWrite(LE,LOW); shiftOut(SDI,CLK,MSBFIRST,(sequence[sequenceNumber][scaledCounter] >> 8)); //High byte first shiftOut(SDI,CLK,MSBFIRST,sequence[sequenceNumber][scaledCounter]); //Low byte second digitalWrite(LE,HIGH); } //If the encoder switch is pushed, this will turn on the bottom LED. The bottom LED is turned //on by 'OR-ing' the current display with 0x8000 (1000000000000000 in binary) if (!digitalRead(ENC_SW)) { digitalWrite(LE,LOW); shiftOut(SDI,CLK,MSBFIRST,((sequence[sequenceNumber][scaledCounter]|0x8000) >> 8)); shiftOut(SDI,CLK,MSBFIRST,sequence[sequenceNumber][scaledCounter]); digitalWrite(LE,HIGH); } } /************************************************************************* * read_encoder() function as provided by Oleg: * * http://www.circuitsathome.com/mcu/reading-rotary-encoder-on-arduino * * * * Returns change in encoder state (-1,0,1) * ************************************************************************ */ int8_t read_encoder() { int8_t enc_states[] = {0,-1,1,0,1,0,0,-1,-1,0,0,1,0,1,-1,0}; static uint8_t old_AB = 0; /**/ old_AB <<= 2; //remember previous state old_AB |= ( ENC_PORT & 0x03 ); //add current state return ( enc_states[( old_AB & 0x0f )]); }
// ----- // RotaryEncoder.cpp - Library for using rotary encoders. // This class is implemented for use with the Arduino environment. // Copyright (c) by Matthias Hertel, http://www.mathertel.de // This work is licensed under a BSD style license. See http://www.mathertel.de/License.aspx // More information on: http://www.mathertel.de/Arduino // ----- // 18.01.2014 created by Matthias Hertel // 17.06.2015 minor updates. // ----- #include "Arduino.h" #include "RotaryEncoder.h" // The array holds the values –1 for the entries where a position was decremented, // a 1 for the entries where the position was incremented // and 0 in all the other (no change or not valid) cases. const int8_t KNOBDIR[] = { 0, -1, 1, 0, 1, 0, 0, -1, -1, 0, 0, 1, 0, 1, -1, 0 }; // positions: [3] 1 0 2 [3] 1 0 2 [3] // [3] is the positions where my rotary switch detends // ==> right, count up // <== left, count down // ----- Initialization and Default Values ----- RotaryEncoder::RotaryEncoder(int pin1, int pin2) { // Remember Hardware Setup _pin1 = pin1; _pin2 = pin2; // Setup the input pins pinMode(pin1, INPUT); digitalWrite(pin1, HIGH); // turn on pullup resistor pinMode(pin2, INPUT); digitalWrite(pin2, HIGH); // turn on pullup resistor // when not started in motion, the current state of the encoder should be 3 _oldState = 3; // start with position 0; _position = 0; _positionExt = 0; } // RotaryEncoder() long RotaryEncoder::getPosition() { return _positionExt; } // getPosition() void RotaryEncoder::setPosition(long newPosition) { // only adjust the external part of the position. _position = ((newPosition<<2) | (_position & 0x03L)); _positionExt = newPosition; } // setPosition() void RotaryEncoder::tick(void) { int sig1 = digitalRead(_pin1); int sig2 = digitalRead(_pin2); int8_t thisState = sig1 | (sig2 << 1); if (_oldState != thisState) { _position += KNOBDIR[thisState | (_oldState<<2)]; if (thisState == LATCHSTATE) _positionExt = _position >> 2; _oldState = thisState; } // if } // tick() // End
//modified from bildr article: http://bildr.org/2012/08/rotary-encoder-arduino/ //these pins can not be changed 2/3 are special pins int encoderPin1 = 2; // breakout PIN A int encoderPin2 = 3; // breakout PIN B int encoderSwitchPin = 4; //breakout PIN SW volatile int lastEncoded = 0; // I don't know why the example used an int and a long to store encoder values. May have overflow error somtime volatile long encoderValue = 0; long lastencoderValue = 0; int lastMSB = 0; int lastLSB = 0; void setup() { Serial.begin (9600); pinMode(encoderPin1, INPUT); pinMode(encoderPin2, INPUT); pinMode(encoderSwitchPin, INPUT); pinMode(5, OUTPUT); pinMode(6, OUTPUT); digitalWrite(encoderPin1, HIGH); //turn pullup resistor on digitalWrite(encoderPin2, HIGH); //turn pullup resistor on digitalWrite(encoderSwitchPin, HIGH); //turn pullup resistor on digitalWrite(6, LOW); digitalWrite(5, LOW); //call updateEncoder() when any high/low changed seen //on interrupt 0 (pin 2), or interrupt 1 (pin 3) attachInterrupt(0, updateEncoder, CHANGE); attachInterrupt(1, updateEncoder, CHANGE); } void loop(){ //Do stuff here if(digitalRead(encoderSwitchPin)){ //button is not being pushed digitalWrite(5, LOW); digitalWrite(6, HIGH); Serial.println("Button NOT Pressed"); } else{ //button is being pushed digitalWrite(6, LOW); digitalWrite(5, HIGH); Serial.println("Button Pressed"); } Serial.println(encoderValue); delay(500); //just here to slow down the output, and show it will work even during a delay } void updateEncoder(){ int MSB = digitalRead(encoderPin1); //MSB = most significant bit int LSB = digitalRead(encoderPin2); //LSB = least significant bit int encoded = (MSB << 1) |LSB; //converting the 2 pin value to single number - creates a value by shifting a MSB to left twice and ORing LSB to that shifted MSB int sum = (lastEncoded << 2) | encoded; //adding it to the previous encoded value - creates new bit value by shifting lastEncoded to left twice and ORing encoded to it. if(sum == 0b1101 || sum == 0b0100 || sum == 0b0010 || sum == 0b1011) encoderValue ++; if(sum == 0b1110 || sum == 0b0111 || sum == 0b0001 || sum == 0b1000) encoderValue --; lastEncoded = encoded; //store this value for next time }
方法
/* Rotary encoder handler for arduino. v1.1 * * Copyright 2011 Ben Buxton. Licenced under the GNU GPL Version 3. * Contact: bb@cactii.net * * A typical mechanical rotary encoder emits a two bit gray code * on 3 output pins. Every step in the output (often accompanied * by a physical 'click') generates a specific sequence of output * codes on the pins. * * There are 3 pins used for the rotary encoding - one common and * two 'bit' pins. * * The following is the typical sequence of code on the output when * moving from one step to the next: * * Position Bit1 Bit2 * ---------------------- * Step1 0 0 * 1/4 1 0 * 1/2 1 1 * 3/4 0 1 * Step2 0 0 * * From this table, we can see that when moving from one 'click' to * the next, there are 4 changes in the output code. * * - From an initial 0 - 0, Bit1 goes high, Bit0 stays low. * - Then both bits are high, halfway through the step. * - Then Bit1 goes low, but Bit2 stays high. * - Finally at the end of the step, both bits return to 0. * * Detecting the direction is easy - the table simply goes in the other * direction (read up instead of down). * * To decode this, we use a simple state machine. Every time the output * code changes, it follows state, until finally a full steps worth of * code is received (in the correct order). At the final 0-0, it returns * a value indicating a step in one direction or the other. * * It's also possible to use 'half-step' mode. This just emits an event * at both the 0-0 and 1-1 positions. This might be useful for some * encoders where you want to detect all positions. * * If an invalid state happens (for example we go from '0-1' straight * to '1-0'), the state machine resets to the start until 0-0 and the * next valid codes occur. * * The biggest advantage of using a state machine over other algorithms * is that this has inherent debounce built in. Other algorithms emit spurious * output with switch bounce, but this one will simply flip between * sub-states until the bounce settles, then continue along the state * machine. * A side effect of debounce is that fast rotations can cause steps to * be skipped. By not requiring debounce, fast rotations can be accurately * measured. * Another advantage is the ability to properly handle bad state, such * as due to EMI, etc. * It is also a lot simpler than others - a static state table and less * than 10 lines of logic. */ #include "Arduino.h" #include "Rotary.h" /* * The below state table has, for each state (row), the new state * to set based on the next encoder output. From left to right in, * the table, the encoder outputs are 00, 01, 10, 11, and the value * in that position is the new state to set. */ #define R_START 0x0 #ifdef HALF_STEP // Use the half-step state table (emits a code at 00 and 11) #define R_CCW_BEGIN 0x1 #define R_CW_BEGIN 0x2 #define R_START_M 0x3 #define R_CW_BEGIN_M 0x4 #define R_CCW_BEGIN_M 0x5 const unsigned char ttable[6][4] = { // R_START (00) {R_START_M, R_CW_BEGIN, R_CCW_BEGIN, R_START}, // R_CCW_BEGIN {R_START_M | DIR_CCW, R_START, R_CCW_BEGIN, R_START}, // R_CW_BEGIN {R_START_M | DIR_CW, R_CW_BEGIN, R_START, R_START}, // R_START_M (11) {R_START_M, R_CCW_BEGIN_M, R_CW_BEGIN_M, R_START}, // R_CW_BEGIN_M {R_START_M, R_START_M, R_CW_BEGIN_M, R_START | DIR_CW}, // R_CCW_BEGIN_M {R_START_M, R_CCW_BEGIN_M, R_START_M, R_START | DIR_CCW}, }; #else // Use the full-step state table (emits a code at 00 only) #define R_CW_FINAL 0x1 #define R_CW_BEGIN 0x2 #define R_CW_NEXT 0x3 #define R_CCW_BEGIN 0x4 #define R_CCW_FINAL 0x5 #define R_CCW_NEXT 0x6 const unsigned char ttable[7][4] = { // R_START {R_START, R_CW_BEGIN, R_CCW_BEGIN, R_START}, // R_CW_FINAL {R_CW_NEXT, R_START, R_CW_FINAL, R_START | DIR_CW}, // R_CW_BEGIN {R_CW_NEXT, R_CW_BEGIN, R_START, R_START}, // R_CW_NEXT {R_CW_NEXT, R_CW_BEGIN, R_CW_FINAL, R_START}, // R_CCW_BEGIN {R_CCW_NEXT, R_START, R_CCW_BEGIN, R_START}, // R_CCW_FINAL {R_CCW_NEXT, R_CCW_FINAL, R_START, R_START | DIR_CCW}, // R_CCW_NEXT {R_CCW_NEXT, R_CCW_FINAL, R_CCW_BEGIN, R_START}, }; #endif /* * Constructor. Each arg is the pin number for each encoder contact. */ Rotary::Rotary(char _pin1, char _pin2) { // Assign variables. pin1 = _pin1; pin2 = _pin2; // Set pins to input. pinMode(pin1, INPUT); pinMode(pin2, INPUT); #ifdef ENABLE_PULLUPS digitalWrite(pin1, HIGH); digitalWrite(pin2, HIGH); #endif // Initialise state. state = R_START; } unsigned char Rotary::process() { // Grab state of input pins. unsigned char pinstate = (digitalRead(pin2) << 1) | digitalRead(pin1); // Determine new state from the pins and state table. state = ttable[state & 0xf][pinstate]; // Return emit bits, ie the generated event. return state & 0x30; }
/* Rotary encoder handler for arduino. v1.1 * * Copyright 2011 Ben Buxton. Licenced under the GNU GPL Version 3. * Contact: bb@cactii.net * * A typical mechanical rotary encoder emits a two bit gray code * on 3 output pins. Every step in the output (often accompanied * by a physical 'click') generates a specific sequence of output * codes on the pins. * * There are 3 pins used for the rotary encoding - one common and * two 'bit' pins. * * The following is the typical sequence of code on the output when * moving from one step to the next: * * Position Bit1 Bit2 * ---------------------- * Step1 0 0 * 1/4 1 0 * 1/2 1 1 * 3/4 0 1 * Step2 0 0 * * From this table, we can see that when moving from one 'click' to * the next, there are 4 changes in the output code. * * - From an initial 0 - 0, Bit1 goes high, Bit0 stays low. * - Then both bits are high, halfway through the step. * - Then Bit1 goes low, but Bit2 stays high. * - Finally at the end of the step, both bits return to 0. * * Detecting the direction is easy - the table simply goes in the other * direction (read up instead of down). * * To decode this, we use a simple state machine. Every time the output * code changes, it follows state, until finally a full steps worth of * code is received (in the correct order). At the final 0-0, it returns * a value indicating a step in one direction or the other. * * It's also possible to use 'half-step' mode. This just emits an event * at both the 0-0 and 1-1 positions. This might be useful for some * encoders where you want to detect all positions. * * If an invalid state happens (for example we go from '0-1' straight * to '1-0'), the state machine resets to the start until 0-0 and the * next valid codes occur. * * The biggest advantage of using a state machine over other algorithms * is that this has inherent debounce built in. Other algorithms emit spurious * output with switch bounce, but this one will simply flip between * sub-states until the bounce settles, then continue along the state * machine. * A side effect of debounce is that fast rotations can cause steps to * be skipped. By not requiring debounce, fast rotations can be accurately * measured. * Another advantage is the ability to properly handle bad state, such * as due to EMI, etc. * It is also a lot simpler than others - a static state table and less * than 10 lines of logic. */ //http://www.buxtronix.net/2011/10/rotary-encoders-done-properly.html /* Modified 5/22/2015 by Phill Fisk * Added methods and constructor to handle button-equiped rotary encoders * Added support methods to return clockwise and counter-clockwise defines */ #include "Arduino.h" #include "rotary.h" /* * The below state table has, for each state (row), the new state * to set based on the next encoder output. From left to right in, * the table, the encoder outputs are 00, 01, 10, 11, and the value * in that position is the new state to set. */ #define R_START 0x0 #ifdef HALF_STEP // Use the half-step state table (emits a code at 00 and 11) #define R_CCW_BEGIN 0x1 #define R_CW_BEGIN 0x2 #define R_START_M 0x3 #define R_CW_BEGIN_M 0x4 #define R_CCW_BEGIN_M 0x5 const unsigned char ttable[6][4] = { // R_START (00) {R_START_M, R_CW_BEGIN, R_CCW_BEGIN, R_START}, // R_CCW_BEGIN {R_START_M | DIR_CCW, R_START, R_CCW_BEGIN, R_START}, // R_CW_BEGIN {R_START_M | DIR_CW, R_CW_BEGIN, R_START, R_START}, // R_START_M (11) {R_START_M, R_CCW_BEGIN_M, R_CW_BEGIN_M, R_START}, // R_CW_BEGIN_M {R_START_M, R_START_M, R_CW_BEGIN_M, R_START | DIR_CW}, // R_CCW_BEGIN_M {R_START_M, R_CCW_BEGIN_M, R_START_M, R_START | DIR_CCW}, }; #else // Use the full-step state table (emits a code at 00 only) #define R_CW_FINAL 0x1 #define R_CW_BEGIN 0x2 #define R_CW_NEXT 0x3 #define R_CCW_BEGIN 0x4 #define R_CCW_FINAL 0x5 #define R_CCW_NEXT 0x6 const unsigned char ttable[7][4] = { // R_START {R_START, R_CW_BEGIN, R_CCW_BEGIN, R_START}, // R_CW_FINAL {R_CW_NEXT, R_START, R_CW_FINAL, R_START | DIR_CW}, // R_CW_BEGIN {R_CW_NEXT, R_CW_BEGIN, R_START, R_START}, // R_CW_NEXT {R_CW_NEXT, R_CW_BEGIN, R_CW_FINAL, R_START}, // R_CCW_BEGIN {R_CCW_NEXT, R_START, R_CCW_BEGIN, R_START}, // R_CCW_FINAL {R_CCW_NEXT, R_CCW_FINAL, R_START, R_START | DIR_CCW}, // R_CCW_NEXT {R_CCW_NEXT, R_CCW_FINAL, R_CCW_BEGIN, R_START}, }; #endif /* * Constructor. Each arg is the pin number for each encoder contact. */ Rotary::Rotary(char _pin1, char _pin2) { // Moved to init method() init(_pin1, _pin2); } /* * Overloaded constructor, added to support rotary encoders that * also include a button */ Rotary::Rotary(char _pin1, char _pin2, char _buttonPin) { // intiialize the rotary encoder button buttonTimer = 0; buttonPin = _buttonPin; pinMode(buttonPin, INPUT); #ifdef ENABLE_PULLUPS digitalWrite(buttonPin, HIGH); #endif // run the original initialization init(_pin1, _pin2); } /* * Moved constructor initialization logic here to support multiple constructors */ void Rotary::init(char _pin1, char _pin2) { // Assign variables. pin1 = _pin1; pin2 = _pin2; // Set pins to input. pinMode(pin1, INPUT); pinMode(pin2, INPUT); #ifdef ENABLE_PULLUPS digitalWrite(pin1, HIGH); digitalWrite(pin2, HIGH); #endif // Initialise state. state = R_START; } unsigned char Rotary::process() { // Grab state of input pins. unsigned char pinstate = (digitalRead(pin2) << 1) | digitalRead(pin1); // Determine new state from the pins and state table. state = ttable[state & 0xf][pinstate]; // Return emit bits, ie the generated event. return state & 0x30; } /* * Added to return clockwise def. makes sketch easier to read * (just check against this method for movement) */ unsigned char Rotary::clockwise() { return DIR_CW; } /* * Added to return counter-clockwise def. makes sketch easier to read * (just check against this method for movement) */ unsigned char Rotary::counterClockwise() { return DIR_CCW; } /* * Reads the rotary encoder button, and returns true if the * button has been pressed and released, based on the debounce dealy passed in * * Presuming the button is wired with one lead to a GPIO pin and the other pin * to ground, the button will read high when open (not pressed) and low when * closed (pressed). In other words, a transition of high -> low -> high (1 -> 0 -> 1) * will indicate a button "press". The debounce delay is configurable (passed in) */ bool Rotary::buttonPressedReleased(short debounce_delay) { if (buttonState == BUTTON_PRESSED) { // If the button has been pressed if (millis() - buttonTimer > debounce_delay) { // and the debounce timer has expired if (digitalRead(buttonPin)) { // and the pin reads HIGH (open) buttonState |= BUTTON_RELEASED; // then the button has been pressed and released } } } else { // if the button hasn't been pressed yet, read the pin if (!digitalRead(buttonPin)) { // if the pin is LOW (closed), then the button has been pushed in buttonState |= BUTTON_PRESSED; // set the state buttonTimer = millis(); // and start the timer } } // Check to see if the button has been pressed and released if (buttonState == (BUTTON_PRESSED | BUTTON_RELEASED)) { buttonState = 0x00; // Reset the button state before returning true return true; } else { return false; } } /* * Reads the encoder button, and returns true if the button has been * pressed and held down for a given amount of time. */ bool Rotary::buttonPressedHeld(short delay_millis) { // Is the button closed (being pressed)? if (!digitalRead(buttonPin)) { // If this is the first time we've checked the button, set the state and start the timer if (buttonState != BUTTON_PRESSED) { buttonState = BUTTON_PRESSED; buttonTimer = millis(); } else { // Otherwise, check the timer to see if it's expired if (millis() - buttonTimer > delay_millis) { // the wait timer has expired, reset the button state buttonState = BUTTON_RESET; // and return true indicating the button has been held down for long enough return true; } } } else { // button is open (not being pressed) was it already pressed? if (buttonState == BUTTON_PRESSED) { // it was pressed and released too quickly, reset it buttonState = BUTTON_RESET; } } return false; } /* * Reads the encoder button and returns the current state (pressed OR released) * Does not return the composite state (just for checking the state right now) */ unsigned char Rotary::readButton() { if (digitalRead(buttonPin)) { return BUTTON_RELEASED; } else { return BUTTON_PRESSED; } } /* * Resets the state of the button */ void Rotary::resetButton() { buttonState = BUTTON_RESET; }

浙公网安备 33010602011771号