Dies hier hat ein Bekannter geschrieben, aber irgendwie funktioniert es nicht.
#include <Wire.h>
#include <LCD.h>
#include <LiquidCrystal_I2C.h>
// ########## INIT DISPLAY ##########
// LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE); // Set the LCD I2C address UNO
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE); // Set the LCD I2C address MEGA2560 ; PIN 20 SDA, PIN 21SCL
// 0x3F correct? see https://www.youtube.com/watch?v=B8DNokj9LnY
// ############ specific configurations ####################
unsigned long idlePeriod = 10000; // time in ms between idle messages or shutdown e.g. 180000
// debug modus: if you need 10 vendors and one additonal PIN (TX0 / Digital PIN 1 which should normally not be used) on UNO turn debug mode to 0 which disables serial
// I use this pin to send a message to my smarthome system for any purchased product
bool debug = true;
bool special_coin_insert = false;
// if (!debug) {
// const int homematic_pin = 1;
// }
unsigned long idleTimerMillis = 0;
int randomNumber = 0;
// ########## Buttons ##########
const int prog_up_button = A1;
const int prog_down_button = A2;
const int prog_next_button = A3;
const int start_button = A4;
const int conf_button = A5;
// ########## Sensors ##########
const int tilt_sensor = A13;
const int ball_sensor = A14;
const int game_coin_sensor = A15;
// ########## INIT VALUES ##########
// #max
// #PREIS
int GameCoinPrice = 10; // default price
int conveyorItems = 999;
int issuecount = 0;
int target_coins = 0;
// ########## INIT COIN ACCEPTOR ##########
const int coinInt = 2; // attach coinInt to interrupt pin 0 = digital pin 2 = digitalPinToInterrupt(2) . (interrupt pin 1 = digital pin 3 = digitalPinToInterrupt(3))
const int coinIntSensor = 3; // attach coinInt to interrupt pin 0 = digital pin 2 = digitalPinToInterrupt(2) . (interrupt pin 1 = digital pin 3 = digitalPinToInterrupt(3))
// set the coinsCurrentValue to a volatile float
// volatile as this variable changes any time the Interrupt is triggered
volatile int coinsCurrentValue = 0;
int coinsChange = 0; // a coin has been inserted flag
unsigned long currentMillis = 0;
unsigned long oldMillis = 0;
int pulsecount;
//const int relays[15] = {22,24,26,28,30,32,34,36,38,40,42,44,46,48,50}; // mega: 15 boxes
const int r_klappe_ok = 22;
const int r_klappe_tilt = 24;
const int r_extra_ball = 26;
const int r_special_coin = 28;
const int hopper = 36;
// ########## END OF INIT ##########
// ########## SETUP ##########
void setup() {
if (debug) {
Serial.begin(9600); // start serial communication
Serial.println("Setup gestartet");
}
pinMode(prog_up_button, INPUT_PULLUP);
pinMode(prog_down_button, INPUT_PULLUP);
pinMode(prog_next_button, INPUT_PULLUP);
pinMode(start_button, INPUT_PULLUP);
pinMode(conf_button, INPUT_PULLUP);
pinMode(tilt_sensor, INPUT_PULLUP);
pinMode(ball_sensor, INPUT_PULLUP);
pinMode(game_coin_sensor, INPUT_PULLUP);
pulsecount = 0;
digitalWrite(r_klappe_ok, HIGH);
pinMode (r_klappe_ok, OUTPUT);
digitalWrite(r_klappe_tilt, HIGH);
pinMode (r_klappe_tilt, OUTPUT);
digitalWrite(r_extra_ball, HIGH);
pinMode (r_extra_ball, OUTPUT);
digitalWrite(r_special_coin, HIGH);
pinMode (r_special_coin, OUTPUT);
digitalWrite(hopper, HIGH);
pinMode (hopper, OUTPUT);
lcd.begin(16, 2); // set up the LCD's number of columns and rows
lcd.print("Bitte warten..."); // Print wait message to the LCD
if (debug) {
Serial.println("Warten auf Muenzpruefer");
}
delay(3000); // don't start main loop until we're sure that the coin selector has started
// if coinInt goes HIGH (a Pulse), call the coinInserted function
// an attachInterrupt will always trigger, even if your using delays
// attachInterrupt(digitalPinToInterrupt(2), coinInserted, RISING);
attachInterrupt(digitalPinToInterrupt(coinInt), coinInserted, RISING);
// (wird direkt in der Routine gemacht:)
// attachInterrupt(digitalPinToInterrupt(coinIntSensor), coinIssued, RISING);
coinsCurrentValue = 0;
lcd.print("Guthaben loeschen.");
delay(200);
if (debug) {
Serial.println("Bereit");
}
lcd.clear();
lcd.print("Bereit.");
}
// ############ coin issued - Lichtschranke ########################
void coinIssued() {
// jetzt erstmal keine weiteren Störungen bitte....
detachInterrupt(digitalPinToInterrupt(coinIntSensor));
if (target_coins > issuecount)
{
coinsCurrentValue = coinsCurrentValue - GameCoinPrice; // reduce balance
}
if (target_coins +1 > issuecount)
{
conveyorItems--; // reduce items
issuecount ++; // count issued coins
if (debug) {
Serial.println(" coin issued: + 1 ");
Serial.println(issuecount);
} //debug
} //if
else
{
digitalWrite(hopper, HIGH);
if (debug) {
Serial.println(" Hopper aus (interupt) ");
} // debug
} //else
// ab hier gern weitere Münzen zählen, die ausgegeben werden:
attachInterrupt(digitalPinToInterrupt(coinIntSensor), coinIssued, FALLING);
}
// ########## COIN INSERT ##########
// This function is called by interrupt every time we receives a pulse from the coin acceptor
void coinInserted() {
coinsChange = 1; // flag that there has been a coin inserted
currentMillis = millis();
int difference = currentMillis - oldMillis;
// Serial.print("difference: ");
if (debug) {
Serial.println(difference);
}
oldMillis = currentMillis;
pulsecount++;
// new coin? start to count from beginning....
if (difference > 134 or difference < 50 ) {
if (pulsecount > 1) {
pulsecount = 1;
}
}
if (difference < 135) {
switch (pulsecount) {
case 2: coinsCurrentValue = coinsCurrentValue + 10;
break;
case 3: coinsCurrentValue = coinsCurrentValue + 10;
break;
case 4: coinsCurrentValue = coinsCurrentValue + 30;
break;
case 5: coinsCurrentValue = coinsCurrentValue + 50;
break;
case 6: coinsCurrentValue = coinsCurrentValue + 100;
break;
case 7: coinsCurrentValue = coinsCurrentValue + 0;
special_coin_insert = true;
break;
} // switch
} // if
idleTimerMillis = millis();
if (debug) {
Serial.print ("(/coinsInserted)neuer Wert: ");
Serial.println ( coinsCurrentValue);
}
}
// ########## Change Coins ##########
void IssueGameCoins() {
if (debug) {
Serial.print(" IssueGameCoins() ");
}
//relais bzw. Hopper direkt ansteuern
digitalWrite(hopper, LOW); // Hoppermotor starten
attachInterrupt(digitalPinToInterrupt(coinIntSensor), coinIssued, RISING);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("*Muenzausgabe*");
delay(3000);
lcd.setCursor(0, 1);
lcd.print(" Bitte warten ");
delay(3000);
lcd.setCursor(0, 0);
lcd.print("Viel Spass! ");
delay(3000);
lcd.setCursor(0, 0);
lcd.print(" Coins oben ");
lcd.setCursor(0, 1);
lcd.print(" einwerfen! ");
delay(3000);
digitalWrite(hopper, HIGH); // Hoppermotor wieder aus falls er nicht schon aus ist
// und Zählen der Impulse beenden
detachInterrupt(digitalPinToInterrupt(coinIntSensor));
if (debug) {
Serial.println(" (Zeit ist um) ");
}
}
// ########## LCD IDLE ##########
// messages on LCD while idle
void idle() {
if ((millis() > idleTimerMillis + idlePeriod) && (coinsCurrentValue < 1) ) {
idleTimerMillis = millis();
randomNumber = random(0, 5); // random number from 0 to 4
lcd.clear();
if (randomNumber == 0) {
lcd.setCursor(0, 0);
// #PREIS
lcd.print(" mach mit!");
lcd.setCursor(0, 1);
lcd.print(" ");
} else if (randomNumber == 1) {
lcd.setCursor(0, 0);
lcd.print("Pruefe dein ");
lcd.setCursor(0, 1);
lcd.print("Geschick. ");
} else if (randomNumber == 2) {
lcd.setCursor(0, 0);
lcd.print("Viel Spass!");
lcd.setCursor(0, 1);
lcd.print(" ");
} else if (randomNumber == 3) {
lcd.setCursor(0, 0);
// #PREIS
lcd.print("Willkommen!");
lcd.setCursor(0, 1);
lcd.print(" ");
} else if (randomNumber == 4) {
lcd.setCursor(0, 0);
lcd.print("Spielmuenze ");
lcd.setCursor(0, 1);
lcd.print("oben einwerfen.");
}
// clear lcd 1000 msec before idle periode expires and no coins have been thrown
if ((millis() > idleTimerMillis + idlePeriod - 1000) && (coinsCurrentValue < 1)) {
lcd.clear();
}
}
}
// ########## SET VALUES ##########
void set_values() {
if (debug) {
Serial.println("Gerätekonfiguration gestartet");
}
// set Anzahl
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("set Zaehler 999");
conveyorItems = 999;
delay(2000);
// Preis ändern
// Setup Preise Button 1 = runterzählen, Button 2 = raufzählen in 10er Schritten, Button 3 = Ende und Anzeige
int scope = 0;
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(" Preis ");
lcd.setCursor(0, 1);
lcd.print(GameCoinPrice / 100.00);
lcd.print(" ");
while (scope == 0) {
if (digitalRead(prog_down_button) == LOW && GameCoinPrice >= 10) {
GameCoinPrice = GameCoinPrice - 10;
displayConfPrice();
delay(500);
}
if (digitalRead(prog_down_button) == LOW && GameCoinPrice > 0 && GameCoinPrice < 10) {
GameCoinPrice = 0;
displayConfPrice();
delay(500);
}
if (digitalRead(prog_up_button) == LOW && GameCoinPrice < 2000) {
GameCoinPrice = GameCoinPrice + 10;
displayConfPrice();
delay(500);
}
if (digitalRead(prog_next_button) == LOW) {
if (debug) {
Serial.print("Neuer Preis: ");
Serial.println(GameCoinPrice / 100.00);
}
scope++;
delay(200);
} //prog_next_button
} // while scope
coinsCurrentValue = 0;
//displayBalance();
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Gespeichert");
delay(200);
displayBalance();
} //set_values
// ########## LCD MESSAGES ##########
void displayBalance() {
if (debug) {
Serial.print("Guthaben: ");
Serial.println(coinsCurrentValue / 100.00);
}
lcd.clear(); // reset LCD
lcd.setCursor(0, 0);
lcd.print("Guthaben");
lcd.setCursor(0, 1); // set cursor to LCD row 2 column 1 (starting with 0)
lcd.write(byte(0)); // display EURO symbol
lcd.print(" ");
lcd.print(coinsCurrentValue / 100.00); // display current balance
}
// ###################################################
void displayPrice(int currentPrice) {
if (debug) {
Serial.print("Spielmuenzenpreis: ");
Serial.println(currentPrice / 100.00);
}
lcd.clear(); // reset LCD
lcd.setCursor(0, 0);
lcd.print("Preis");
lcd.setCursor(0, 1); // set cursor to LCD row 2 column 1 (starting with 0)
lcd.print(" ");
lcd.print(currentPrice / 100.00);
if (coinsCurrentValue > 0) {
delay(1000);
displayBalance();
}
}
// ###################################################
void displayEmpty() {
if (debug) {
Serial.println("Muenzen alle");
}
lcd.clear(); // reset LCD
lcd.setCursor(0, 0);
lcd.print("Leider leer :(");
lcd.setCursor(0, 1); // set cursor to LCD row 2 column 1 (starting with 0)
lcd.print(" ");
if (coinsCurrentValue > 0) {
delay(1000);
displayBalance();
}
}
// ###################################################
void displayConfPrice() {
lcd.setCursor(0, 1);
lcd.print(GameCoinPrice / 100.00);
lcd.print(" ");
}
// ########## MAIN LOOP ##########
void loop() {
// ## Config Button pressed ##
if (digitalRead(conf_button) == LOW) {
if (debug) {
Serial.print("DigitalRead(conf_button): LOW");
}
set_values();
delay(1000);
} //config_button pressed
// ## game_coin_sensor detects game coin - das Spiel beginnt, Klappe bereit ##
if (digitalRead(game_coin_sensor) == LOW) {
if (debug) {
Serial.print("game coins sensor detects gamecoin: LOW");
}
digitalWrite(r_klappe_ok, LOW); // Klappe bereit
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Coin eingeworfen,");
lcd.setCursor(0, 1);
lcd.print(" los geht's! ");
delay(1000);
digitalWrite(r_klappe_ok, HIGH); // Klappe ist bereit, Spule kann aus..
} //game_coin_sensor
// ## TILT sensor ##
if (digitalRead(tilt_sensor) == LOW) {
if (debug) {
Serial.print("TILT!!: LOW");
}
digitalWrite(r_klappe_tilt, LOW); // Tilt - alle Münzen fallen ins Depot!
delay(1000);
digitalWrite(r_klappe_tilt, HIGH); // Tilt-Klappe ist ausgelöst, weiter geht es mit dem Einwurf (game_coin_sensor)
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("*TILT !! ;o( ");
lcd.setCursor(0, 1);
lcd.print(" Spiel beendet. ");
} //Tilt sensor
// ## Ball sensor ##
if (digitalRead(ball_sensor) == LOW) {
if (debug) {
Serial.print("Ball Sensor - Freispiel: LOW");
}
digitalWrite(r_extra_ball, LOW); // Extraball ausgeben
delay(1000);
digitalWrite(r_extra_ball, HIGH); // Extraball ist ausgegeben
delay(500);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("*Extraball! ");
lcd.setCursor(0, 1);
lcd.print(" Freispiel? ");
digitalWrite(r_special_coin, LOW); // Spezialmünze ausgeben
delay(1000);
digitalWrite(r_special_coin, HIGH); // Spezialmünze ist ausgegeben
} //Ball sensor
idle();
// check if a coin has been inserted
if (coinsChange == 1) {
if (special_coin_insert)
{
special_coin_insert = false;
// digitalWrite(r_special_coin, LOW); // Spezialmünze ausgeben weil eine eingesteckt wurde
// delay(1000);
// digitalWrite(r_special_coin, HIGH); // Spezialmünze ist ausgegeben
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("*Sondermuenze: ");
lcd.setCursor(0, 1);
lcd.print(" Freispiele!");
delay(2000);
} // Sonderverarbeitung der Sondermünze
coinsChange = 0; // unflag that a coin has been inserted
displayBalance(); // display current balance
}
// ********** BUTTON PRESSED **********
if (digitalRead(start_button) == LOW) { // start button pressed (GameCoins ausgeben)
if (debug) {
Serial.print(" items ");
Serial.print(conveyorItems);
Serial.print(" cval ");
Serial.print(coinsCurrentValue);
Serial.print(" price ");
Serial.print(GameCoinPrice);
}
if (conveyorItems > 0) {
if (coinsCurrentValue < GameCoinPrice) { // insufficient balance - display price
Serial.print(" insuf ");
displayPrice(GameCoinPrice);
idleTimerMillis = millis();
delay(200);
}
if ((coinsCurrentValue > GameCoinPrice - 1) ) { // sufficient balance
if (debug) {
Serial.print(" suf ");
}
target_coins = coinsCurrentValue / GameCoinPrice;
issuecount = 0;
IssueGameCoins();
if (coinsCurrentValue < 0) {
coinsCurrentValue = 0; // correct float rounding error
}
displayBalance(); // display current balance
idleTimerMillis = millis(); // reset idle timer
delay(2000);
} // sufficient balance
} // items > 0
} // start_button pressed
} // loop