// Download this in a .zip file.
/* Test the freetronics 16x2 LCD shield http://www.freetronics.com/pages/16x2-lcd-shield-quickstart-guide#.UBKMm7T9OK9 MTG Life Counter by eturnerx@gmail.com 201208 */ /*-------------------------------------------------------------------------------------- Includes --------------------------------------------------------------------------------------*/ #include// include LCD library /*-------------------------------------------------------------------------------------- Defines --------------------------------------------------------------------------------------*/ // Pins in use #define BUTTON_ADC_PIN A0 // A0 is the button ADC input #define LCD_BACKLIGHT_PIN 3 // D3 controls LCD backlight // ADC readings expected for the 5 buttons on the ADC input #define RIGHT_10BIT_ADC 0 // right #define UP_10BIT_ADC 145 // up #define DOWN_10BIT_ADC 329 // down #define LEFT_10BIT_ADC 505 // left #define SELECT_10BIT_ADC 741 // right #define BUTTONHYSTERESIS 10 // hysteresis for valid button sensing window //return values for ReadButtons() #define BUTTON_NONE 0 // #define BUTTON_RIGHT 1 // #define BUTTON_UP 2 // #define BUTTON_DOWN 3 // #define BUTTON_LEFT 4 // #define BUTTON_SELECT 5 // /*-------------------------------------------------------------------------------------- Variables --------------------------------------------------------------------------------------*/ byte buttonJustPressed = false; //this will be true after a ReadButtons() call if triggered byte buttonJustReleased = false; //this will be true after a ReadButtons() call if triggered byte buttonWas = BUTTON_NONE; //used by ReadButtons() for detection of button events int life1 = 20; int life2 = 20; int who = 0; int resetcounter = 0; /*-------------------------------------------------------------------------------------- Init the LCD library with the LCD pins to be used --------------------------------------------------------------------------------------*/ LiquidCrystal lcd( 8, 9, 4, 5, 6, 7 ); //Pins for the freetronics 16x2 LCD shield. LCD: ( RS, E, LCD-D4, LCD-D5, LCD-D6, LCD-D7 ) /*-------------------------------------------------------------------------------------- setup() Called by the Arduino framework once, before the main loop begins --------------------------------------------------------------------------------------*/ void setup() { //button adc input pinMode( BUTTON_ADC_PIN, INPUT ); //ensure A0 is an input digitalWrite( BUTTON_ADC_PIN, LOW ); //ensure pullup is off on A0 //lcd backlight control digitalWrite( LCD_BACKLIGHT_PIN, HIGH ); //backlight control pin D3 is high (on) pinMode( LCD_BACKLIGHT_PIN, OUTPUT ); //D3 is an output //set up the LCD number of columns and rows: lcd.begin( 16, 2 ); //Print some initial text to the LCD. lcd.setCursor( 0, 0 ); //top left // 1234567890123456 lcd.print( "MTG Life Counter" ); updateLifeCounts(); } /*-------------------------------------------------------------------------------------- loop() Arduino main loop --------------------------------------------------------------------------------------*/ void loop() { byte button; button = ReadButtons(); //show text label for the button pressed switch(button) { case BUTTON_NONE: resetcounter = 0; break; case BUTTON_LEFT: if(buttonJustPressed) { who = 0; } break; case BUTTON_RIGHT: if(buttonJustPressed) { who = 1; } break; case BUTTON_UP: if(buttonJustPressed) { if(who == 0) life1++; else life2++; } break; case BUTTON_DOWN: if(buttonJustPressed) { if(who == 0) life1--; else life2--; } break; case BUTTON_SELECT: //SELECT is a special case, it pulses the LCD backlight off and on for demo digitalWrite( LCD_BACKLIGHT_PIN, LOW ); delay( 150 ); digitalWrite( LCD_BACKLIGHT_PIN, HIGH ); //leave the backlight on at exit delay( 150 ); resetcounter++; if(resetcounter > 10) { resetcounter = 0; life1 = 20; life2 = 20; updateLifeCounts(); } break; default: break; } //Output the update life totals. if(buttonJustPressed || buttonJustReleased ) updateLifeCounts(); //clear the buttonJustPressed or buttonJustReleased flags, they've already done their job now. if(buttonJustPressed) buttonJustPressed = false; if(buttonJustReleased) buttonJustReleased = false; delay(20); } /*-------------------------------------------------------------------------------------- ReadButtons() Detect the button pressed and return the value Uses global values buttonWas, buttonJustPressed, buttonJustReleased. --------------------------------------------------------------------------------------*/ byte ReadButtons() { unsigned int buttonVoltage; byte button = BUTTON_NONE; // return no button pressed if the below checks don't write to btn //read the button ADC pin voltage buttonVoltage = analogRead( BUTTON_ADC_PIN ); //sense if the voltage falls within valid voltage windows if( buttonVoltage < ( RIGHT_10BIT_ADC + BUTTONHYSTERESIS ) ) { button = BUTTON_RIGHT; } else if( buttonVoltage >= ( UP_10BIT_ADC - BUTTONHYSTERESIS ) && buttonVoltage <= ( UP_10BIT_ADC + BUTTONHYSTERESIS ) ) { button = BUTTON_UP; } else if( buttonVoltage >= ( DOWN_10BIT_ADC - BUTTONHYSTERESIS ) && buttonVoltage <= ( DOWN_10BIT_ADC + BUTTONHYSTERESIS ) ) { button = BUTTON_DOWN; } else if( buttonVoltage >= ( LEFT_10BIT_ADC - BUTTONHYSTERESIS ) && buttonVoltage <= ( LEFT_10BIT_ADC + BUTTONHYSTERESIS ) ) { button = BUTTON_LEFT; } else if( buttonVoltage >= ( SELECT_10BIT_ADC - BUTTONHYSTERESIS ) && buttonVoltage <= ( SELECT_10BIT_ADC + BUTTONHYSTERESIS ) ) { button = BUTTON_SELECT; } //handle button flags for just pressed and just released events if( ( buttonWas == BUTTON_NONE ) && ( button != BUTTON_NONE ) ) { //the button was just pressed, set buttonJustPressed, this can optionally be used to trigger a once-off action for a button press event //it's the duty of the receiver to clear these flags if it wants to detect a new button change event buttonJustPressed = true; buttonJustReleased = false; } if( ( buttonWas != BUTTON_NONE ) && ( button == BUTTON_NONE ) ) { buttonJustPressed = false; buttonJustReleased = true; } //save the latest button value, for change event detection next time round buttonWas = button; return( button ); } void updateLifeCounts() { lcd.setCursor( 0, 1 ); if(life1 < 10 && life1 > 0) lcd.print(" "); if(life1 <= 0) lcd.print("XX"); else if(life1 > 99) lcd.print("99"); else lcd.print(life1); if(who == 0) lcd.print("*"); else lcd.print(" "); // 1234567890123456 lcd.print(" "); lcd.setCursor( 13, 1 ); if(who == 1) lcd.print("*"); else lcd.print(" "); if(life2 < 10 && life2 > 0) lcd.print(" "); if(life2 <= 0) lcd.print("XX"); else if(life2 > 99) lcd.print("99"); else lcd.print(life2); }