#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(); } }