Hello everyone! I'd like to ask for help with my coin acceptor. So my coin acceptor is wired to D2, every time it powers up, it accepts coins and the blue LED on my ESP8266 pulses depending on how much was inserted (i.e. 5 peso coin -> 5 pulses), but for some reason, at times it just stops counting/crediting. For example, I put 10 pesos, it should count to 10, but stops at 5 or 6 randomly. Then when I insert another coin, it accepts it, but it no longer counts the credit. When I restart the system, it returns to normal, but after some time, it stops abruptly again. Here's my entire code for the system:
#include <Adafruit_Thermal.h>
#include <SoftwareSerial.h>
#include <LiquidCrystal_I2C.h>
#include "vglogoII.h"
//Network time
#include "NTPClient.h"
#include "ESP8266WiFi.h"
#include "WiFiUdp.h"
//Wifi, Date & Time
const char *ssid = "Wifi";
const char *password = "********";
WiFiUDP ntpUDP;
const long utcOffsetInSeconds = 28800;
NTPClient timeClient(ntpUDP, "time.nist.gov", utcOffsetInSeconds);
//Pin assignment
const int BTN_LED_PIN = 0;
const int COIN_PIN = 2;
const int INSERT_COIN_BTN_PIN = 3;
const int COIN_SET_PIN = 15;
int TX_PIN = 14; //Green Wire
int RX_PIN = 16; //Yellow Wire
LiquidCrystal_I2C lcd(0x27, 16, 2);
SoftwareSerial mySerial(RX_PIN, TX_PIN);
Adafruit_Thermal printer(&mySerial);
//Button variables
int btnState = 0;
volatile bool btnPressed = false;
bool btnDisabled = false;
//Coin/coinslot variables
volatile int impulseCount = 0;
int coinType = 0;
int totalAmount = 0;
int coinValue;
const int coinPulses[] = { 1, 5, 10 };
bool firstCoinOn = true;
//Countdown variables
unsigned long previousMillis = 0;
int countdown = 16;
int countdownII = 11;
const long interval = 1000;
bool countdownStarted = false;
bool countdownIIStarted = false;
//Transaction flag
bool ongoingTransaction = false;
int lookup(int pulses) {
for(int i = 0; i < sizeof(coinPulses) / sizeof(coinPulses[0]); i++) {
if (pulses == coinPulses[i]) {
return coinPulses[i];
}
}
return -1;
}
void IRAM_ATTR coinInterrupt() {
if(firstCoinOn) {
countdownStarted = true;
} else {
impulseCount++;
}
firstCoinOn = false;
}
void IRAM_ATTR btnInterrupt() {
static unsigned long lastExec = 0;
unsigned long currentExec = millis();
if(currentExec - lastExec > 500 && !btnDisabled) {
lcd.clear();
btnPressed = true;
btnDisabled = true;
btnState++;
}
lastExec = currentExec;
}
void setup() {
Serial.begin(9600);
mySerial.begin(9600);
pinMode(BTN_LED_PIN, OUTPUT);
pinMode(COIN_PIN, INPUT_PULLUP);
pinMode(INSERT_COIN_BTN_PIN, INPUT_PULLUP);
pinMode(COIN_SET_PIN, OUTPUT);
digitalWrite(BTN_LED_PIN, LOW);
digitalWrite(COIN_SET_PIN, LOW);
attachInterrupt(digitalPinToInterrupt(COIN_PIN), coinInterrupt, RISING);
attachInterrupt(digitalPinToInterrupt(INSERT_COIN_BTN_PIN), btnInterrupt, FALLING);
lcd.init();
lcd.clear();
lcd.backlight();
printer.begin();
printer.sleep();
delay(1000L);
printer.wake();
WiFi.begin(ssid, password);
while(WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
timeClient.begin();
}
void loop() {
timeClient.update();
if(!ongoingTransaction) {
lcd.setCursor(1, 0);
lcd.print("VGWifi Hotspot");
lcd.setCursor(2, 1);
lcd.print(" ");
lcd.setCursor(2, 1);
lcd.print("Press button");
digitalWrite(BTN_LED_PIN, HIGH);
delay(600);
lcd.setCursor(2, 1);
lcd.print(" ");
digitalWrite(BTN_LED_PIN, LOW);
delay(600);
}
//Credit counter
if(impulseCount == coinPulses[coinType]) {
Serial.print("Impulse: ");
Serial.println(impulseCount);
coinValue = lookup(impulseCount);
if(totalAmount == 0 || countdownIIStarted) {
lcd.clear();
}
if(coinValue > 0) {
totalAmount += coinValue;
}
Serial.print("Total Amount: ");
Serial.println(totalAmount);
impulseCount = 0;
lcd.setCursor(0, 0);
lcd.print("Total credits: ");
lcd.setCursor(0, 1);
lcd.print("P");
lcd.print(totalAmount);
lcd.print(".00");
}
if(btnPressed) {
time_t epochTime = timeClient.getEpochTime();
struct tm *ptm = gmtime ((time_t *)&epochTime);
int currentMonth = ptm->tm_mon+1;
int monthDay = ptm->tm_mday;
int currentYear = ptm->tm_year+1900;
String date = String(currentMonth) +"-" +monthDay +"-" +currentYear +" " + String(timeClient.getFormattedTime());
switch(btnState) {
case 1:
enableCoinSlot();
lcd.begin(16, 2);
ongoingTransaction = true;
btnPressed = false;
digitalWrite(BTN_LED_PIN, LOW);
lcd.setCursor(0, 0);
lcd.print("Insert coins now");
break;
case 2:
disableCoinSlot();
getVoucher(totalAmount, date);
btnPressed = false;
digitalWrite(BTN_LED_PIN, LOW);
delay(5000);
btnDisabled = false;
lcd.clear();
btnState = 0;
firstCoinOn = true;
ongoingTransaction = false;
totalAmount = 0;
break;
}
}
unsigned long currentMillis = millis();
//Countdown for insert coins
if(countdownStarted && (currentMillis - previousMillis >= interval)) {
previousMillis = currentMillis;
countdown--;
if(countdown < 10) {
lcd.setCursor(15, 1);
lcd.print(" ");
}
lcd.setCursor(11, 1); // Set cursor position
lcd.print("(");
lcd.print(countdown);
lcd.print("s)");
}
if(countdownIIStarted && (currentMillis - previousMillis >= interval)) {
previousMillis = currentMillis;
countdownII--;
if (countdownII < 10) {
lcd.setCursor(15, 1);
lcd.print(" ");
}
lcd.setCursor(14, 1); // Set cursor position
lcd.print(countdownII);
}
if(countdown <= 0) {
if(totalAmount >= 5) {
displayPrintPrompt();
} else {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Not enough coins");
lcd.setCursor(0, 1);
lcd.print("Insert more");
countdownIIStarted = true;
}
countdown = 16;
countdownStarted = false;
}
if(countdownII <= 0) {
//Still insuff balance, return home
if(totalAmount < 5) {
lcd.clear();
disableCoinSlot();
btnState = 0;
btnDisabled = false;
countdownII = 11;
countdownIIStarted = false;
ongoingTransaction = false;
firstCoinOn = true;
} else {
countdownII = 11;
countdownIIStarted = false;
displayPrintPrompt();
}
}
}
void displayPrintPrompt() {
btnDisabled = false;
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Print voucher?");
lcd.setCursor(0, 1);
lcd.print("Press button");
disableCoinSlot();
digitalWrite(BTN_LED_PIN, HIGH);
}
void enableCoinSlot() {
digitalWrite(COIN_SET_PIN, HIGH);
}
void disableCoinSlot() {
digitalWrite(COIN_SET_PIN, LOW);
}
void getVoucher(int amt, String dateTime) {
Serial.print("AMT: ");
Serial.println(String(amt));
String code;
int tier;
String valid;
int change;
if(amt >= 5 && amt < 10) {
tier = 5;
valid = "30 MINS";
} else if(amt >= 10 && amt < 15) {
tier = 10;
valid = "1 HOUR";
} else if(amt >= 15 && amt < 25) {
tier = 15;
valid = "3 HOURS";
} else if(amt >= 25 && amt < 35) {
tier = 25;
valid = "1 DAY";
} else if(amt >= 35 && amt <50) {
tier = 35;
valid = "3 DAYS";
} else {
tier = 50;
valid = "7 DAYS";
}
change = amt-tier;
lcd.print("Voucher code:");
lcd.setCursor(1, 1);
lcd.print("885912 ");
lcd.print(valid);
printVoucher("885912", tier, valid, change, dateTime);
}
void printVoucher(String code, int amount, String valid, int change, String dateTime) {
String tier = " (P" +String(amount) +".00)";
printer.printBitmap(232, 82, VGWifi);
printer.setSize('S');
printer.println("");
printer.justify('C');
printer.setFont('C');
printer.setSize('M');
printer.println("Voucher Code:");
printer.setSize('L');
printer.println(code);
printer.setSize('S');
printer.println("");
printer.setSize('M');
printer.print("Valid for: ");
printer.print(valid);
printer.println(tier);
printer.boldOff();
printer.setSize('S');
if(change != 0) {
printer.print("Your change is: P");
printer.print(change);
printer.println(".00");
}
printer.println("Thank you for purchasing!");
printer.print(dateTime);
printer.println("\n");
printer.setSize('L');
printer.println(F("\n"));
printer.sleep();
delay(3000L);
printer.wake();
printer.setDefault();
}
Sorry for the long code and the question. Thank you for your responses!