Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // include the Arduino LCD and math libraries
- #include <LiquidCrystal.h>
- // States
- #define S_idle 1
- #define S_ready 2
- #define S_coin 3
- #define S_set_timer 4
- #define S_pause 5
- #define S_override 6
- #define S_limit 7
- #define S_countdown 8
- #define S_timeup 9
- // Default startup state
- int state = S_idle;
- // LCD PINs
- LiquidCrystal lcd(7, 8, 9, 10, 11, 12);
- // Display backlight pins
- const int LCDr = 3;
- const int LCDg = 5;
- const int LCDb = 6;
- // Other PINs
- const int CoinSW = 2;
- const int VideoSW = 4;
- const int StartSW = A0;
- const int PauseSW = A1;
- const int CoinLED = A2;
- const int OverrideSW = A3;
- const int VideoDetect = A4;
- const int Speaker = A5;
- // Button debounce vars
- int buttonState;
- int lastButtonState = HIGH;
- long lastDebounceTime = 0;
- long debounceDelay = 50;
- // Coin counting and time vars
- unsigned long AllowedPlaytime;
- unsigned long CurrentMillis;
- int CoinCount = 0;
- int CoinTimeValue = 30; // Amount of time (in minutes) that the coin is worth.
- int DepositStringIndex = 0;
- int TimeStringIndex = 0;
- // Video on/off switching vars
- int VideoSwitchState = LOW;
- long VideoSwitchBuffer = 2000; // Add some seconds to AllowedPlaytime after video ON switching event to compensate for TV sync time.
- unsigned long SwitchPreviousMillis = 0;
- long VideoSwitchInterval = 500;
- // Warning beep vars
- unsigned long LastWarningTime = 0;
- long WarningBeepInterval1 = 60000; // 60 seconds
- long WarningBeepInterval2 = 1000; // 1 seconds
- bool ClearLCD = false;
- bool PauseRun = false;
- // Strings for the deposit display
- char* DepositStrings[]= {
- " ", // Placeholder does not display.
- "$0.25", // 30 min
- "$0.50", // 1 hour
- "$0.75", // 1.5 hours
- "$1.00", // 2 hours
- "$1.25", // 2.5 hours
- "$1.50", // 3 hours
- "$1.75", // 3.5 hours
- "$2.00", // 4 hours
- "$2.25", // 4.5 hours
- "$2.50", // 5 hours
- "$2.75", // 5.5 hours
- "$3.00", // 6 hours
- "$3.25", // 6.5 hours
- "$3.75", // 7 hours
- "$4.00", // 7.5 hours
- "$4.25", // Placeholder does not display.
- };
- char* TimeStrings[]= {
- " ", // Placeholder does not display.
- "30m ",
- "1h ",
- "1.5h ",
- "2h ",
- "2.5h ",
- "3h ",
- "3.5h ",
- "4h ",
- "4.5h ",
- "5h ",
- "5.5h ",
- "6h ",
- "6.5h ",
- "7h ",
- "7.5h ",
- "8h ", // Placeholder does not display.
- };
- // Characters for display on the LCD.
- byte armsUp[8] = {
- 0b00100,
- 0b01010,
- 0b00100,
- 0b10101,
- 0b01110,
- 0b00100,
- 0b00100,
- 0b01010
- };
- byte armsDown[8] = {
- 0b00100,
- 0b01010,
- 0b00100,
- 0b00100,
- 0b01110,
- 0b10101,
- 0b00100,
- 0b01010
- };
- byte smiley[8] = {
- 0b00000,
- 0b00000,
- 0b01010,
- 0b00000,
- 0b00000,
- 0b10001,
- 0b01110,
- 0b00000
- };
- byte frownie[8] = {
- 0b00000,
- 0b00000,
- 0b01010,
- 0b00000,
- 0b00000,
- 0b00000,
- 0b01110,
- 0b10001
- };
- void setup() {
- // Initilize the LCD
- lcd.begin(16, 2);
- // Set PINs as inputs or outputs.
- pinMode(LCDr, OUTPUT);
- pinMode(LCDg, OUTPUT);
- pinMode(LCDb, OUTPUT);
- pinMode(VideoSW, OUTPUT);
- pinMode(Speaker, OUTPUT);
- pinMode(CoinSW, INPUT);
- pinMode(StartSW, INPUT);
- pinMode(PauseSW, INPUT);
- pinMode(CoinLED, OUTPUT);
- pinMode(OverrideSW, INPUT);
- pinMode(VideoDetect,INPUT);
- // Enable internal resistors on button PINs so we don't have to use external resistors.
- digitalWrite(CoinSW, HIGH);
- digitalWrite(StartSW, HIGH);
- digitalWrite(PauseSW, HIGH);
- digitalWrite(OverrideSW, HIGH);
- digitalWrite(VideoDetect, HIGH);
- // Initilize special LCD charaters.
- lcd.createChar(1, armsUp);
- lcd.createChar(2, armsDown);
- lcd.createChar(3, smiley);
- lcd.createChar(4, frownie);
- // For testing comment out in production.
- Serial.begin(9600);
- }
- void loop() {
- switch(state) {
- case S_idle:
- F_idle();
- break;
- case S_ready:
- F_ready();
- break;
- case S_override:
- F_override();
- break;
- case S_coin:
- F_coin();
- break;
- case S_limit:
- F_limit();
- break;
- case S_set_timer:
- F_set_timer();
- break;
- case S_countdown:
- F_countdown();
- break;
- case S_timeup:
- F_timeup();
- break;
- case S_pause:
- F_pause();
- break;
- }
- }
- // Functions //
- void F_idle() {
- LCDBacklight(255, 0, 0); // Red
- lcd.setCursor(2, 0);
- lcd.write(2);
- lcd.print(" NOT READY ");
- lcd.write(2);
- lcd.setCursor(3, 1);
- lcd.print("Press START");
- DepositStringIndex = 0; // Reset
- TimeStringIndex = 0; // Reset
- CoinCount =0; // Reset
- // If it's on, turn the video off.
- while (digitalRead(VideoDetect) == LOW) {
- F_video_off();
- }
- if (digitalRead(StartSW) == LOW) { // Button logic is invertid since we're using the internal resistors. When button is pressed the PIN goes LOW, when not pressed it's HIGH.
- lcd.clear();
- state = S_ready;
- }
- if (digitalRead(OverrideSW) == LOW){
- lcd.clear();
- state = S_override;
- }
- }
- void F_ready() {
- LCDBacklight(0, 255, 0);
- lcd.setCursor(4, 0);
- lcd.write(1);
- lcd.print(" READY ");
- lcd.write(1);
- lcd.setCursor(2, 1);
- lcd.print("Insert Coins");
- digitalWrite(CoinLED, HIGH);
- if (digitalRead(CoinSW) == LOW) {
- lcd.clear();
- state = S_coin;
- }
- }
- void F_override() {
- if (ClearLCD == true) {
- ClearLCD = false;
- lcd.clear();
- }
- // Turn the video on.
- while (digitalRead(VideoDetect) == HIGH) {
- F_video_on();
- }
- LCDBacklight(255,255,0); // Yellow
- lcd.setCursor(3, 0);
- lcd.print("Override On");
- lcd.setCursor(2, 1);
- lcd.write(3);
- lcd.print(" Lucky You ");
- lcd.write(3);
- if (digitalRead(OverrideSW) == HIGH){
- lcd.clear();
- state = S_idle;
- }
- }
- void F_coin() {
- LCDBacklight(255, 153, 0); // Orange
- lcd.setCursor(0, 0);
- lcd.print("Deposited:");
- lcd.print(DepositStrings[DepositStringIndex]);
- lcd.setCursor(0, 1);
- lcd.print("Playtime:");
- lcd.print(TimeStrings[TimeStringIndex]);
- // We need to debounce the coin counting switch. Otherwise we'd count several coins when only one was deposited.
- int reading = digitalRead(CoinSW) == LOW;
- if (reading != lastButtonState) {
- lastDebounceTime = millis();
- }
- if ((millis() - lastDebounceTime) > debounceDelay) {
- if (reading != buttonState) {
- buttonState = reading;
- if (buttonState == LOW) { // Logic is invertid since we're using the internal resistors. When button is pressed the PIN goes LOW, when not pressed it's HIGH.
- CoinCount = CoinCount + CoinTimeValue; // Count the coin deposit.
- DepositStringIndex++;
- TimeStringIndex++;
- }
- }
- }
- lastButtonState = reading;
- // Done debouncing and depositing.
- if (DepositStringIndex == 15) {
- CoinCount = CoinCount + CoinTimeValue; // System does not grab the last coin deposited when it hits the limit so we count it here.
- lcd.clear();
- digitalWrite(CoinLED, LOW);
- state = S_limit;
- }
- if (digitalRead(StartSW) == LOW) { // Logic is inverted since we're using the internal resistors. When button is pressed the PIN goes LOW, when not pressed it's HIGH.
- lcd.clear();
- digitalWrite(CoinLED, LOW);
- state = S_set_timer;
- }
- }
- void F_limit() {
- LCDBacklight(255, 0, 0); // Red
- lcd.setCursor(2, 0);
- lcd.print("8 Hour Limit");
- lcd.setCursor(3, 1);
- lcd.print("Press START");
- if (digitalRead(StartSW) == LOW) { // Logic is inverted since we're using the internal resistors. When button is pressed the PIN goes LOW, when not pressed it's HIGH.
- lcd.clear();
- state = S_set_timer;
- }
- }
- void F_set_timer() {
- AllowedPlaytime = CoinCount * 60000; // Multiply the CoinCount by 60000 (milliseconds) to get teh AllowedPlaytime.
- // Turn the video on.
- while (digitalRead(VideoDetect) == HIGH) {
- F_video_on();
- }
- AllowedPlaytime = AllowedPlaytime + VideoSwitchBuffer; // Add some time (VideoSwitchBuffer) to make up for the time it took the TV to sync back up and display video.
- state = S_countdown;
- }
- void F_countdown() {
- if (ClearLCD == true) {
- lcd.clear();
- ClearLCD = false;
- }
- LCDBacklight(0, 0, 255); // Blue
- lcd.setCursor(2, 0);
- lcd.print("Time Started:");
- // If second has passed then we subtract that from the AllowedPlaytime
- if (millis() - CurrentMillis > 1000) {
- AllowedPlaytime = AllowedPlaytime - 1000;
- CurrentMillis = millis();
- F_timeDisplay();
- // If there is less than 5 minutes of playtime left start sounding an audible alarm at the interval defined.
- if (AllowedPlaytime <= 300000) { // 5 min
- if (millis() - LastWarningTime > WarningBeepInterval1) {
- F_warning1();
- }
- // Or if there is less than 10 seconds of playtime left start sounding an audible alarm at the interval defined.
- else if (AllowedPlaytime <= 10000) { // 10 seconds
- if (millis() - LastWarningTime > WarningBeepInterval2) {
- F_warning2();
- }
- }
- }
- }
- if (digitalRead(PauseSW) == LOW) { // Logic is inverted since we're using the internal resistors. When button is pressed the PIN goes LOW, when not pressed it's HIGH.
- lcd.clear();
- state = S_pause;
- }
- if (AllowedPlaytime == 0) {
- lcd.clear();
- state = S_timeup;
- }
- }
- void F_pause() {
- LCDBacklight(255, 0, 255); // Pink
- lcd.setCursor(2, 0);
- lcd.print("Time Paused:");
- F_timeDisplay();
- // Turn the video off to prevent abuse of the pause.
- while (digitalRead(VideoDetect) == LOW) {
- F_video_off();
- }
- if (digitalRead(StartSW) == LOW) { // Logic is inverted since we're using the internal resistors. When button is pressed the PIN goes LOW, when not pressed it's HIGH.
- lcd.clear();
- // Turn the video back on since we unpaused.
- while (digitalRead(VideoDetect) == HIGH) {
- F_video_on();
- }
- AllowedPlaytime = AllowedPlaytime + VideoSwitchBuffer; // Add some time (VideoSwitchBuffer) to make up for the time it took to turn the video on.
- state = S_countdown;
- }
- }
- void F_timeup() {
- LCDBacklight(255, 255, 0); // Yellow
- lcd.setCursor(2, 0);
- lcd.write(4);
- lcd.print(" Times Up ");
- lcd.write(4);
- tone(Speaker, 2000, 1000);
- while (digitalRead(VideoDetect) == LOW) {
- F_video_off();
- }
- delay(5000);
- state = S_idle;
- }
- void F_timeDisplay() {
- lcd.setCursor(4, 1);
- int seconds = AllowedPlaytime / 1000;
- int minutes = seconds / 60;
- int hours = minutes / 60;
- seconds = seconds % 60;
- minutes = minutes % 60;
- if (hours < 10) {
- lcd.print("0");
- lcd.print(hours);
- lcd.print(":");
- if (minutes < 10)
- lcd.print("0");
- lcd.print(minutes);
- lcd.print(":");
- if (seconds < 10)
- lcd.print("0");
- lcd.print(seconds);
- }
- }
- void F_video_on() {
- LCDBacklight(255,255,0); // Yellow
- lcd.setCursor(5, 0);
- lcd.print("Standby");
- lcd.setCursor(0, 1);
- lcd.print("Turning Video On");
- unsigned long CurrentMillis = millis();
- if(CurrentMillis - SwitchPreviousMillis > VideoSwitchInterval) {
- SwitchPreviousMillis = CurrentMillis;
- if (VideoSwitchState == LOW)
- VideoSwitchState = HIGH;
- else
- VideoSwitchState = LOW;
- digitalWrite(VideoSW, VideoSwitchState);
- }
- ClearLCD = true;
- }
- void F_video_off() {
- unsigned long CurrentMillis = millis();
- if(CurrentMillis - SwitchPreviousMillis > VideoSwitchInterval) {
- SwitchPreviousMillis = CurrentMillis;
- if (VideoSwitchState == LOW)
- VideoSwitchState = HIGH;
- else
- VideoSwitchState = LOW;
- digitalWrite(VideoSW, VideoSwitchState);
- }
- }
- void F_warning1() {
- tone(Speaker, 500, 1000);
- LastWarningTime = millis();
- }
- void F_warning2() {
- tone(Speaker, 1000, 200);
- LastWarningTime = millis();
- }
- void LCDBacklight(uint8_t r, uint8_t g, uint8_t b) {
- // common anode so invert!
- r = map(r, 0, 255, 255, 0);
- g = map(g, 0, 255, 255, 0);
- b = map(b, 0, 255, 255, 0);
- analogWrite(LCDr, r);
- analogWrite(LCDg, g);
- analogWrite(LCDb, b);
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement