- #include <avr/sleep.h>
- #include <avr/interrupt.h>
- #include <SoftwareSerial.h>
-
- const int rx = -1; // -1 = dont use
- const int tx = 5; // pin 5 for serial.print()
- SoftwareSerial Serial(rx,tx); // rx, tx pins
-
- int enc1pinA = 2; // Encoder pin A
- int enc1pinB = 3; // Encoder pin B
- int counter = 0; // could use a byte here?
- byte enc1oldPins = 0; // will hold state of pins last time encoder was read
- byte enc1newPins = 0; // will hold new encoder pin reading, to be compared with last time's pin states
- byte enc1move = 0; // when two encoders are used to control the same parameter, this will hold the combined deduced movement
-
- const byte RotaryDecodeTable[4][4] = {
- {B00, B10, B01, B11},
- {B01, B00, B11, B10},
- {B10, B11, B00, B01},
- {B11, B01, B10, B00}
- };
-
- int bLed = 1; // rotary encoder LED pin
- int rgLed = 4; // red/green LED pin
- int val = 0; // rotary encoder current position
-
- unsigned long lastCheck = 0; // time (for sleep state)
- bool sleepState = 0; // sleep or awake
-
- void setup() {
- pinMode(bLed, OUTPUT);
- pinMode(rgLed, INPUT);
-
- pinMode(enc1pinA, INPUT); // configure the pin connections as inputs
- pinMode(enc1pinB, INPUT);
- pinMode(enc1pinA, INPUT_PULLUP); // turn on internal pull-up resistor for each input
- pinMode(enc1pinB, INPUT_PULLUP);
- delay(1); // allow 1ms for encoder voltages to setle
- enc1oldPins = (digitalRead(enc1pinA)<<1|digitalRead(enc1pinB)); // read the initial state of encoder
-
- lastCheck = millis(); // for sleep state
-
- pinMode(rx,INPUT); // setup and print to serial
- pinMode(tx,OUTPUT);
- Serial.begin(9600);
- Serial.println("Running");
- }
-
- void green(int del){ // turn on green LED for delay()
- pinMode(rgLed, OUTPUT);
- analogWrite(rgLed, HIGH);
- delay(del);
- pinMode(rgLed, INPUT);
- }
- void red(int del){ // turn on red LED for delay()
- pinMode(rgLed, OUTPUT);
- analogWrite(rgLed, 255);
- delay(del);
- pinMode(rgLed, INPUT);
- }
-
- void keepAwake(int dir){ // runs every time rottary encoder is turned to keep deviec awake
- lastCheck = millis();
- if(sleepState == 1){
- sleepState = 0;
- }
- }
-
- void sleep(){
- println("Sleeping");
- sleepState = 1;
- analogWrite(bLed, LOW);
-
- GIMSK |= _BV(PCIE); // Enable Pin Change Interrupts
- PCMSK |= _BV(PCINT2); // Use pin 2 as interrupt pin
- PCMSK |= _BV(PCINT3); // Use pin 3 as interrupt pin
- PCMSK &= ~_BV(PCINT3); // Turn off pin 3 as interrupt pin
- ADCSRA &= ~_BV(ADEN); // ADC off
- set_sleep_mode(SLEEP_MODE_PWR_DOWN); // replaces above statement
-
- sleep_enable(); // Sets the Sleep Enable bit in the MCUCR Register (SE BIT)
- sei(); // Enable interrupts
- sleep_cpu(); // sleep
-
- cli(); // Disable interrupts
- PCMSK &= ~_BV(PCINT3); // Turn off PB3 as interrupt pin
- sleep_disable(); // Clear SE bit
- ADCSRA |= _BV(ADEN); // ADC on
-
- sei(); // Enable interrupts
- }
-
- void loop(){
- enc1newPins = 0; // Empty byte ready to shift-in new pins
- enc1newPins = (digitalRead(enc1pinA)<<1|digitalRead(enc1pinB)); // read the current state of encoder1 pins
- enc1move = RotaryDecodeTable[enc1oldPins][enc1newPins]; // used RotaryDecodeTable to decide movement, if any
- enc1oldPins = enc1newPins; // update encoder1state to be current pin values
- if (enc1move == B01){ // if result was move right (CW), decrement counter
- counter--;
- keepAwake();
- }
- if (enc1move == B10){ // if result was move left (anti-CW), inrement counter
- counter++;
- keepAwake();
- }
-
- // inactive > 10 secs so go into sleep state
- if ( (millis() - lastCheck > 10000) && sleepState == 0 ) { // 10000 == 10 secs
- sleep();
- }
- }