#include <TM1637.h>
#include <WiFi.h>
#include <HTTPClient.h>
#define SSID "Wokwi-GUEST"
#define PASSWORD ""
#define DEBOUNCE_TIME 250
#define DEBOUNCE_TIME_COIN 100
#define LED_PIN 23
#define CLK 15
#define DIO 2
#define GOOGLE_SHEET_URL "https://echo.free.beeceptor.com/googlesheet"
TM1637 TM1; // Each display needs its own object
unsigned long previousMillisClock; // for the millis timer of the first display
const unsigned long intervalClock = 500; //1000;
bool colon = false; // for a toggling of the colon in the middle.
unsigned long previousMillisCountDown; // for a millis timer of second display
const unsigned long intervalCountDown = 100;
int clockSeconds; // the seconds counter for the first display
int clockMinutes; // the minute counter for the first display
int countDown = 9999; // start value of down counter for second display
int clock500ms;
char buffer[5]; // buffer for third display
struct Button {
const uint8_t PIN;
uint32_t numberKeyPresses;
bool pressed;
//variables to keep track of the timing of recent interrupts
unsigned long button_time;
unsigned long last_button_time;
};
struct Relay {
const uint8_t PIN;
bool isOn;
const uint8_t pricePerSec; // ราคาสตางค์ต่อวินาที
uint8_t countdown;
};
Button buttonCoin = {34, 0, false, 0, 0};
Button button1 = {35, 0, false, 0, 0};
Button button2 = {32, 0, false, 0, 0};
Button button3 = {33, 0, false, 0, 0};
Button button4 = {25, 0, false, 0, 0};
Button button5 = {26, 0, false, 0, 0};
Button button6 = {27, 0, false, 0, 0};
Button button7 = {14, 0, false, 0, 0};
Button button8 = {13, 0, false, 0, 0};
Relay relay1 = {22, false, 50, 0};
Relay relay2 = {21, false, 25, 0};
Relay relay3 = {19, false, 50, 0};
Relay relay4 = {18, false, 25, 0};
Relay relay5 = {5, false, 50, 0};
Relay relay6 = {17, false, 25, 0};
Relay relay7 = {16, false, 50, 0};
Relay relay8 = {4, false, 25, 0};
const int PRICE_PER_COIN = 100; // สตางค์
int totalAmount = 0;
int totalCoin = 0;
const bool RELAY_ON = 0; //active low
const bool RELAY_OFF = 1; //active low
uint16_t onTimerCount = 0;
uint16_t onTimerCountLast = 0;
hw_timer_t *My_timer = NULL;
void IRAM_ATTR onTimer() {
// digitalWrite(LED_PIN, !digitalRead(LED_PIN));
onTimerCount++;
}
void IRAM_ATTR isrCoin() {
buttonCoin.button_time = millis();
if (buttonCoin.button_time - buttonCoin.last_button_time > DEBOUNCE_TIME_COIN)
{
buttonCoin.numberKeyPresses++;
buttonCoin.pressed = true;
buttonCoin.last_button_time = buttonCoin.button_time;
totalCoin++;
totalAmount += PRICE_PER_COIN;
}
}
void IRAM_ATTR isr1() {
button1.button_time = millis();
if (button1.button_time - button1.last_button_time > DEBOUNCE_TIME)
{
button1.numberKeyPresses++;
button1.pressed = true;
button1.last_button_time = button1.button_time;
if (relay1.isOn) {
relayAllOff();
}
else {
if (relay1.isOn || relay2.isOn || relay3.isOn || relay4.isOn ||
relay5.isOn || relay6.isOn || relay7.isOn || relay8.isOn ) {
relayAllOff();
}
else if (totalAmount ) {
digitalWrite(relay1.PIN, RELAY_ON);
relay1.isOn = true;
}
}
}
}
void IRAM_ATTR isr2() {
button2.button_time = millis();
if (button2.button_time - button2.last_button_time > DEBOUNCE_TIME)
{
button2.numberKeyPresses++;
button2.pressed = true;
button2.last_button_time = button2.button_time;
if (relay2.isOn) {
relayAllOff();
}
else {
if (relay1.isOn || relay2.isOn || relay3.isOn || relay4.isOn ||
relay5.isOn || relay6.isOn || relay7.isOn || relay8.isOn ) {
relayAllOff();
}
else if (totalAmount ) {
digitalWrite(relay2.PIN, RELAY_ON);
relay2.isOn = true;
}
}
}
}
void IRAM_ATTR isr3() {
button3.button_time = millis();
if (button3.button_time - button3.last_button_time > DEBOUNCE_TIME)
{
button3.numberKeyPresses++;
button3.pressed = true;
button3.last_button_time = button3.button_time;
if (relay3.isOn) {
relayAllOff();
}
else {
if (relay1.isOn || relay2.isOn || relay3.isOn || relay4.isOn ||
relay5.isOn || relay6.isOn || relay7.isOn || relay8.isOn ) {
relayAllOff();
}
else if (totalAmount ) {
digitalWrite(relay3.PIN, RELAY_ON);
relay3.isOn = true;
}
}
}
}
void IRAM_ATTR isr4() {
button4.button_time = millis();
if (button4.button_time - button4.last_button_time > DEBOUNCE_TIME)
{
button4.numberKeyPresses++;
button4.pressed = true;
button4.last_button_time = button4.button_time;
if (relay4.isOn) {
relayAllOff();
}
else {
if (relay1.isOn || relay2.isOn || relay3.isOn || relay4.isOn ||
relay5.isOn || relay6.isOn || relay7.isOn || relay8.isOn ) {
relayAllOff();
}
else if (totalAmount ) {
digitalWrite(relay4.PIN, RELAY_ON);
relay4.isOn = true;
}
}
}
}
void IRAM_ATTR isr5() {
button5.button_time = millis();
if (button5.button_time - button5.last_button_time > DEBOUNCE_TIME)
{
button5.numberKeyPresses++;
button5.pressed = true;
button5.last_button_time = button5.button_time;
if (relay5.isOn) {
relayAllOff();
}
else {
if (relay1.isOn || relay2.isOn || relay3.isOn || relay4.isOn ||
relay5.isOn || relay6.isOn || relay7.isOn || relay8.isOn ) {
relayAllOff();
}
else if (totalAmount ) {
digitalWrite(relay5.PIN, RELAY_ON);
relay5.isOn = true;
}
}
}
}
void IRAM_ATTR isr6() {
button6.button_time = millis();
if (button6.button_time - button6.last_button_time > DEBOUNCE_TIME)
{
button6.numberKeyPresses++;
button6.pressed = true;
button6.last_button_time = button6.button_time;
if (relay6.isOn) {
relayAllOff();
}
else {
if (relay1.isOn || relay2.isOn || relay3.isOn || relay4.isOn ||
relay5.isOn || relay6.isOn || relay7.isOn || relay8.isOn ) {
relayAllOff();
}
else if (totalAmount ) {
digitalWrite(relay6.PIN, RELAY_ON);
relay6.isOn = true;
}
}
}
}
void IRAM_ATTR isr7() {
button7.button_time = millis();
if (button7.button_time - button7.last_button_time > DEBOUNCE_TIME)
{
button7.numberKeyPresses++;
button7.pressed = true;
button7.last_button_time = button7.button_time;
if (relay7.isOn) {
relayAllOff();
}
else {
if (relay1.isOn || relay2.isOn || relay3.isOn || relay4.isOn ||
relay5.isOn || relay6.isOn || relay7.isOn || relay8.isOn ) {
relayAllOff();
}
else if (totalAmount ) {
digitalWrite(relay7.PIN, RELAY_ON);
relay7.isOn = true;
}
}
}
}
void IRAM_ATTR isr8() {
button8.button_time = millis();
if (button8.button_time - button8.last_button_time > DEBOUNCE_TIME)
{
button8.numberKeyPresses++;
button8.pressed = true;
button8.last_button_time = button8.button_time;
if (relay8.isOn) {
relayAllOff();
}
else {
if (relay1.isOn || relay2.isOn || relay3.isOn || relay4.isOn ||
relay5.isOn || relay6.isOn || relay7.isOn || relay8.isOn ) {
relayAllOff();
}
else if (totalAmount ) {
digitalWrite(relay8.PIN, RELAY_ON);
relay8.isOn = true;
}
}
}
}
void relayAllOff() {
digitalWrite(relay1.PIN, RELAY_OFF);
digitalWrite(relay2.PIN, RELAY_OFF);
digitalWrite(relay3.PIN, RELAY_OFF);
digitalWrite(relay4.PIN, RELAY_OFF);
digitalWrite(relay5.PIN, RELAY_OFF);
digitalWrite(relay6.PIN, RELAY_OFF);
digitalWrite(relay7.PIN, RELAY_OFF);
digitalWrite(relay8.PIN, RELAY_OFF);
relay1.isOn = false;
relay2.isOn = false;
relay3.isOn = false;
relay4.isOn = false;
relay5.isOn = false;
relay6.isOn = false;
relay7.isOn = false;
relay8.isOn = false;
}
void countdownTask() {
if (totalAmount ) {
if (relay1.isOn) {
totalAmount -= relay1.pricePerSec;
Serial.printf("relay1 isOn totalAmount = %u \n", totalAmount);
digitalWrite(relay1.PIN, RELAY_ON);
}
else if (relay2.isOn) {
totalAmount -= relay2.pricePerSec;
Serial.printf("relay1 isOn totalAmount = %u \n", totalAmount);
digitalWrite(relay2.PIN, RELAY_ON);
}
else if (relay3.isOn) {
totalAmount -= relay3.pricePerSec;
Serial.printf("relay3 isOn totalAmount = %u \n", totalAmount);
digitalWrite(relay3.PIN, RELAY_ON);
}
else if (relay4.isOn) {
totalAmount -= relay4.pricePerSec;
Serial.printf("relay4 isOn totalAmount = %u \n", totalAmount);
digitalWrite(relay4.PIN, RELAY_ON);
}
else if (relay5.isOn) {
totalAmount -= relay5.pricePerSec;
Serial.printf("relay5 isOn totalAmount = %u \n", totalAmount);
digitalWrite(relay5.PIN, RELAY_ON);
}
else if (relay6.isOn) {
totalAmount -= relay2.pricePerSec;
Serial.printf("relay1 isOn totalAmount = %u \n", totalAmount);
digitalWrite(relay2.PIN, RELAY_ON);
}
else if (relay7.isOn) {
totalAmount -= relay7.pricePerSec;
Serial.printf("relay7 isOn totalAmount = %u \n", totalAmount);
digitalWrite(relay7.PIN, RELAY_ON);
}
else if (relay8.isOn) {
totalAmount -= relay8.pricePerSec;
Serial.printf("relay8 isOn totalAmount = %u \n", totalAmount);
digitalWrite(relay8.PIN, RELAY_ON);
}
totalCoin = totalAmount / 100;
Serial.printf("totalCoin = %u \n", totalCoin);
TM1.displayInt(totalCoin);
if (totalAmount <= 0) {
totalAmount = 0;
relayAllOff();
}
}
}
void sendToGoogleSheet(uint16_t value) {
if (WiFi.status() == WL_CONNECTED) {
HTTPClient http;
String url = String(GOOGLE_SHEET_URL) + "?sensor=A0&value=" + String(value);
Serial.println("Making a request");
http.begin(url.c_str()); //Specify the URL and certificate
http.setFollowRedirects(HTTPC_STRICT_FOLLOW_REDIRECTS);
int httpCode = http.GET();
String payload;
if (httpCode > 0) { //Check for the returning code
payload = http.getString();
Serial.println(httpCode);
Serial.println(payload);
}
else {
Serial.println("Error on HTTP request");
}
http.end();
}
}
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
Serial.println("Hello, coin acceptor countdown timer!");
// uint32_t Freq = getCpuFrequencyMhz();
// Serial.print("CPU Freq = ");
// Serial.print(Freq);
// Serial.println(" MHz");
// Freq = getXtalFrequencyMhz();
// Serial.print("XTAL Freq = ");
// Serial.print(Freq);
// Serial.println(" MHz");
// Freq = getApbFrequency();
// Serial.print("APB Freq = ");
// Serial.print(Freq);
// Serial.println(" Hz");
pinMode(buttonCoin.PIN, INPUT_PULLUP);
pinMode(button1.PIN, INPUT_PULLUP);
pinMode(button2.PIN, INPUT_PULLUP);
pinMode(button3.PIN, INPUT_PULLUP);
pinMode(button4.PIN, INPUT_PULLUP);
pinMode(button5.PIN, INPUT_PULLUP);
pinMode(button6.PIN, INPUT_PULLUP);
pinMode(button7.PIN, INPUT_PULLUP);
pinMode(button8.PIN, INPUT_PULLUP);
pinMode(relay1.PIN, OUTPUT);
pinMode(relay2.PIN, OUTPUT);
pinMode(relay3.PIN, OUTPUT);
pinMode(relay4.PIN, OUTPUT);
pinMode(relay5.PIN, OUTPUT);
pinMode(relay6.PIN, OUTPUT);
pinMode(relay7.PIN, OUTPUT);
pinMode(relay8.PIN, OUTPUT);
digitalWrite(relay1.PIN, RELAY_OFF);
digitalWrite(relay2.PIN, RELAY_OFF);
digitalWrite(relay3.PIN, RELAY_OFF);
digitalWrite(relay4.PIN, RELAY_OFF);
digitalWrite(relay5.PIN, RELAY_OFF);
digitalWrite(relay6.PIN, RELAY_OFF);
digitalWrite(relay7.PIN, RELAY_OFF);
digitalWrite(relay8.PIN, RELAY_OFF);
attachInterrupt(buttonCoin.PIN, isrCoin, FALLING);
attachInterrupt(button1.PIN, isr1, FALLING);
attachInterrupt(button2.PIN, isr2, FALLING);
attachInterrupt(button3.PIN, isr3, FALLING);
attachInterrupt(button4.PIN, isr4, FALLING);
attachInterrupt(button5.PIN, isr5, FALLING);
attachInterrupt(button6.PIN, isr6, FALLING);
attachInterrupt(button7.PIN, isr7, FALLING);
attachInterrupt(button8.PIN, isr8, FALLING);
// -----------------------------------------
// First display
// -----------------------------------------
TM1.begin(CLK, DIO, 4); // clockpin, datapin, #digits
TM1.displayClear();
TM1.setBrightness(7); // full brightness, default is 3
TM1.displayPChar("----"); // Initial text on third display
Serial.print("Connecting to WiFi");
WiFi.begin(SSID, PASSWORD, 6);
while (WiFi.status() != WL_CONNECTED) {
delay(100);
Serial.print(".");
}
Serial.println(" Connected!");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
pinMode(LED_PIN, OUTPUT);
My_timer = timerBegin(0, 80, true);
timerAttachInterrupt(My_timer, &onTimer, true);
timerAlarmWrite(My_timer, 1000000, true);
timerAlarmEnable(My_timer); //Just Enable
}
void loop() {
unsigned long currentMillis = millis();
// -----------------------------------------
// First display
// -----------------------------------------
// if ( !totalAmount && currentMillis - previousMillisClock >= intervalClock)
// {
// previousMillisClock += intervalClock; // for a clock-accurate millis timer
// TM1.displayTime(clockMinutes, clockSeconds, colon); // display the numbers
// colon = !colon; // toggle colon
// // increment time
// if (++clock500ms % 2) clockSeconds++;
// if (clockSeconds >= 120) //60
// {
// clockSeconds = 0;
// clockMinutes++;
// if (clockMinutes >= 60)
// {
// clockMinutes = 0;
// }
// }
// }
if (onTimerCount != onTimerCountLast) {
// Serial.printf("onTimerCount = %u, onTimerCountLast = %u \n", onTimerCount, onTimerCountLast);
countdownTask();
onTimerCountLast = onTimerCount;
if(relay1.isOn || relay2.isOn || relay3.isOn || relay4.isOn ||
relay5.isOn || relay6.isOn || relay7.isOn || relay8.isOn ) {
digitalWrite(LED_PIN, !digitalRead(LED_PIN));
}
else if(totalCoin) {
digitalWrite(LED_PIN, 0); // on
}
else {
digitalWrite(LED_PIN, 1); // off
}
}
if (buttonCoin.pressed) {
Serial.printf("Button coin totalAmount = %u, totalCoin = %u \n", totalAmount, totalCoin );
buttonCoin.pressed = false;
// sendToGoogleSheet(totalCoin);
}
if (button1.pressed) {
Serial.printf("Button 1 pressed, totalAmount = %u, relay1.pricePerSec = %u, isOn = %u\n", totalAmount, relay1.pricePerSec, relay1.isOn);
button1.pressed = false;
}
if (button2.pressed) {
Serial.printf("Button 2 pressed, totalAmount = %u, relay2.pricePerSec = %u, isOn = %u\n", totalAmount, relay2.pricePerSec, relay2.isOn);
button2.pressed = false;
}
if (button3.pressed) {
Serial.printf("Button 3 pressed, totalAmount = %u, relay3.pricePerSec = %u, isOn = %u\n", totalAmount, relay3.pricePerSec, relay3.isOn);
button3.pressed = false;
}
if (button4.pressed) {
Serial.printf("Button 4 pressed, totalAmount = %u, relay4.pricePerSec = %u, isOn = %u\n", totalAmount, relay4.pricePerSec, relay4.isOn);
button4.pressed = false;
}
if (button5.pressed) {
Serial.printf("Button 5 pressed, totalAmount = %u, relay5.pricePerSec = %u, isOn = %u\n", totalAmount, relay5.pricePerSec, relay5.isOn);
button5.pressed = false;
}
if (button6.pressed) {
Serial.printf("Button 6 pressed, totalAmount = %u, relay6.pricePerSec = %u, isOn = %u\n", totalAmount, relay6.pricePerSec, relay6.isOn);
button6.pressed = false;
}
if (button7.pressed) {
Serial.printf("Button 7 pressed, totalAmount = %u, relay7.pricePerSec = %u, isOn = %u\n", totalAmount, relay7.pricePerSec, relay7.isOn);
button7.pressed = false;
}
if (button8.pressed) {
Serial.printf("Button 8 pressed, totalAmount = %u, relay8.pricePerSec = %u, isOn = %u\n", totalAmount, relay8.pricePerSec, relay8.isOn);
button8.pressed = false;
}
}