// ROFLS+ Arena Controller #include #include // automatically installed for ESP32 boards, I think? #include // automatically installed for ESP32 boards #include // https://fastled.io/ #include // https://github.com/avdwebLibraries/avdweb_Switch #include // https://github.com/RobTillaart/CountDown #include // https://github.com/RobTillaart/StopWatch_RT // Hardware connections #define START_BTN_PIN 1 #define PAUSE_BTN_PIN 2 #define PIT_BTN_PIN 3 #define RESET_BTN_PIN 4 #define RUMBLE_SWITCH_PIN 5 #define PIT_ENABLE_SWITCH_PIN 6 #define RED_TEAM_BTN_PIN 7 #define RED_TEAM_LED_PIN 39 #define BLUE_TEAM_BTN_PIN 6 #define BLUE_TEAM_LED_PIN 40 #define PIT_RELEASE_PIN 35 // LED Strip setup #define NUM_LEDS_PER_DIGIT 56 #define NUM_OF_DIGITS 4 #define NUM_LEDS_COLON 8 #define NUM_LEDS_TIMER (NUM_LEDS_PER_DIGIT * NUM_OF_DIGITS + NUM_LEDS_COLON) // + 1 because of the makeshift Levelshifter #define LED_DATA_PIN_TIMER 16 // This is an array of leds. One item for each led in your strip. CRGB leds_TIMER[NUM_LEDS_TIMER]; // define buttons and switches Switch buttonSTART = Switch(START_BTN_PIN); Switch buttonPAUSE = Switch(PAUSE_BTN_PIN); Switch buttonPIT = Switch(PIT_BTN_PIN); Switch buttonRESET = Switch(RESET_BTN_PIN); Switch switchRUMBLE = Switch(RUMBLE_SWITCH_PIN); Switch switchPIT = Switch(PIT_ENABLE_SWITCH_PIN); Switch buttonREDTEAM = Switch(RED_TEAM_BTN_PIN); Switch buttonBLUETEAM = Switch(BLUE_TEAM_BTN_PIN); bool buttonSTARTvar = false; bool buttonPAUSEvar = false; bool buttonPITvar = false; bool buttonRESETvar = false; bool buttonREDTEAMvar = false; bool buttonBLUETEAMvar = false; unsigned long PITopenTimestamp = 0; const long PITopenTime = 1000; // activate solenoid for 1000ms bool PITreleased = false; const int countdownTIME = 3; // countdown timer length in minutes const int countdownToFight = 3; // countdown timer length in seconds const int PITreleaseTime = 90; // automatic pit release time in seconds until end of countdown bool countdownPAUSED = false; CountDown FightCountDown[1]; // Rumble stopwatch StopWatch rumbleTIME; int prevMINUTES = 0; int prevSECONDS = 0; int prevCLOCKRED = 0; int prevCLOCKGREEN = 0; int prevCLOCKBLUE = 0; int CLOCK_LED_BRIGHTNESS = 16; // 64 is okay int BLINK_COUNTER_REDTEAM = 0; int BLINK_COUNTER_BLUETEAM = 0; bool ARENA_READY = true; bool REDTEAM_READY = false; bool BLUETEAM_READY = false; // ESP-NOW config // Structure example to send data // Must match the receiver structure typedef struct struct_message { bool buttonSTARTremote; bool buttonPAUSEremote; bool buttonPITremote; bool buttonRESETremote; bool buttonREDTEAMremote; bool buttonBLUETEAMremote; } struct_message; // Create a struct_message called remoteDATA struct_message remoteDATA; // callback function that will be executed when data is received void OnDataRecv(const uint8_t * mac, const uint8_t *incomingData, int len) { memcpy(&remoteDATA, incomingData, sizeof(remoteDATA)); if (remoteDATA.buttonSTARTremote) { buttonSTARTvar = true; } if (remoteDATA.buttonPAUSEremote) { buttonPAUSEvar = true; } if (remoteDATA.buttonPITremote) { buttonPITvar = true; } if (remoteDATA.buttonRESETremote) { buttonRESETvar = true; } } void setup() { // set outputs pinMode(RED_TEAM_LED_PIN, OUTPUT); pinMode(BLUE_TEAM_LED_PIN, OUTPUT); pinMode(PIT_RELEASE_PIN, OUTPUT); digitalWrite(BLUE_TEAM_LED_PIN, LOW); digitalWrite(RED_TEAM_LED_PIN, LOW); digitalWrite(PIT_RELEASE_PIN, LOW); Serial.begin(115200); // Set device as a Wi-Fi Station WiFi.mode(WIFI_STA); // Init ESP-NOW if (esp_now_init() != ESP_OK) { Serial.println("Error initializing ESP-NOW"); return; } // Once ESPNow is successfully Init, we will register for recv CB to // get recv packer info esp_now_register_recv_cb(esp_now_recv_cb_t(OnDataRecv)); // set rumble stopwatch resolution to seconds // sanity check delay - allows reprogramming if accidently blowing power w/leds delay(2000); // This function sets up the leds and tells the controller about them FastLED.addLeds(leds_TIMER, NUM_LEDS_TIMER); // GRB ordering is typical //FastLED.setMaxRefreshRate(10, true); FastLED.setMaxPowerInVoltsAndMilliamps(5,2000); // Limit to 10W of output power } int XDAS = 255; bool toggle = false; void loop() { // poll all the switch/button inputs pollInput(); // deactivate solenoids if needed checkPIT(); // Normal fight routine while (!switchRUMBLE.on()) { // poll all the switch/button inputs pollInput(); // deactivate solenoids if needed checkPIT(); // start button logic if (buttonSTARTvar) { buttonSTARTvar = false; if (!FightCountDown[0].isRunning() && countdownPAUSED == false) { if (buttonREDTEAMvar && buttonBLUETEAMvar) { buttonREDTEAMvar = false; buttonBLUETEAMvar = false; FightCountDown[0].start(0,0,countdownTIME,0); } } else { if (buttonREDTEAMvar && buttonBLUETEAMvar) { buttonREDTEAMvar = false; buttonBLUETEAMvar = false; countdownPAUSED = false; FightCountDown[0].cont(); } } } // pause button logic if (buttonPAUSEvar) { buttonPAUSEvar = false; if (FightCountDown[0].isRunning()) { countdownPAUSED = true; FightCountDown[0].stop(); } } // pit button logic if (buttonPITvar) { buttonPITvar = false; openPIT(); } // automatic pit release if (FightCountDown[0].remaining() <= PITreleaseTime && FightCountDown[0].remaining() > 0 && switchPIT.on()) { openPIT(); } // reset button logic if (buttonRESETvar) { buttonRESETvar = false; PITreleased = false; ESP.restart(); } blink_LED_RedTeam(200); blink_LED_BlueTeam(200); // update the LED Display showTimeDisplay((FightCountDown[0].remaining()/60%10), (FightCountDown[0].remaining()%60), 0, XDAS, 0); } // Rumble fightroutine while (switchRUMBLE.on()) { // poll all the switch/button inputs pollInput(); // deactivate solenoids if needed checkPIT(); // update the LED Display showTimeDisplay(12, 34, XDAS, 0, XDAS); } }