initial commit

This commit is contained in:
2025-02-22 20:45:28 +01:00
commit d0d8c2ac7a
10 changed files with 804 additions and 0 deletions

View File

@@ -0,0 +1,38 @@
// handle all the inputs, set vars, etc.
void pollInput (){
// poll all the switch/button inputs
buttonSTART.poll();
buttonPAUSE.poll();
buttonPIT.poll();
buttonRESET.poll();
switchRUMBLE.poll();
switchPIT.poll();
buttonREDTEAM.poll();
buttonBLUETEAM.poll();
if (buttonSTART.pushed()) {
buttonSTARTvar = true;
}
if (buttonPAUSE.pushed()) {
buttonPAUSEvar = true;
}
if (buttonPIT.pushed()) {
buttonPITvar = true;
}
if (buttonRESET.pushed()) {
buttonRESETvar = true;
}
if (buttonREDTEAM.pushed()) {
buttonREDTEAMvar = true;
if (ARENA_READY && !REDTEAM_READY) {
BLINK_COUNTER_REDTEAM = 5;
}
}
if (buttonBLUETEAM.pushed()) {
buttonBLUETEAMvar = true;
if (ARENA_READY && !BLUETEAM_READY) {
BLINK_COUNTER_BLUETEAM = 5;
}
}
}

View File

@@ -0,0 +1,133 @@
// contains all the functions to drive the LEDs
// 0
const int LitArray0 [] = {8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55};
// 1
const int LitArray1 [] = {8,9,10,11,12,13,14,15,48,49,50,51,52,53,54,55};
// 2
const int LitArray2 [] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47};
// 3
const int LitArray3 [] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55};
// 4
const int LitArray4 [] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,24,25,26,27,28,29,30,31,48,49,50,51,52,53,54,55};
// 5
const int LitArray5 [] = {0,1,2,3,4,5,6,7,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55};
// 6
const int LitArray6 [] = {0,1,2,3,4,5,6,7,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55};
// 7
const int LitArray7 [] = {8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,48,49,50,51,52,53,54,55};
// 8
const int LitArray8 [] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55};
// 9
const int LitArray9 [] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55};
// colon
const int COLONArray [] = {224,225,226,227,228,229,230,231};
// set digits of the timer/clock, use: setDIGIT(<digit ID>, <Number>, <red channel intensity 0-255>, <green channel intensity 0-255>, <blue channel intensity 0-255>)
void setDIGIT(int DIGIT_ID, int DIGIT, int RED, int GREEN, int BLUE) {
DIGIT_ID = map(DIGIT_ID, 1, 4, 0, 3); // swap index/ID number from 1-4 to 0-3
switch (DIGIT) {
case 0:
// set 0
for (int i : LitArray0) {
leds_TIMER[i + (NUM_LEDS_PER_DIGIT * DIGIT_ID )].setRGB(RED,GREEN,BLUE);
}
break;
case 1:
// set 1
for (int i : LitArray1) {
leds_TIMER[i + (NUM_LEDS_PER_DIGIT * DIGIT_ID )].setRGB(RED,GREEN,BLUE);
}
break;
case 2:
// set 2
for (int i : LitArray2) {
leds_TIMER[i + (NUM_LEDS_PER_DIGIT * DIGIT_ID )].setRGB(RED,GREEN,BLUE);
}
break;
case 3:
// set 3
for (int i : LitArray3) {
leds_TIMER[i + (NUM_LEDS_PER_DIGIT * DIGIT_ID )].setRGB(RED,GREEN,BLUE);
}
break;
case 4:
// set 4
for (int i : LitArray4) {
leds_TIMER[i + (NUM_LEDS_PER_DIGIT * DIGIT_ID )].setRGB(RED,GREEN,BLUE);
}
break;
case 5:
// set 5
for (int i : LitArray5) {
leds_TIMER[i + (NUM_LEDS_PER_DIGIT * DIGIT_ID )].setRGB(RED,GREEN,BLUE);
}
break;
case 6:
// set 6
for (int i : LitArray6) {
leds_TIMER[i + (NUM_LEDS_PER_DIGIT * DIGIT_ID )].setRGB(RED,GREEN,BLUE);
}
break;
case 7:
// set 7
for (int i : LitArray7) {
leds_TIMER[i + (NUM_LEDS_PER_DIGIT * DIGIT_ID )].setRGB(RED,GREEN,BLUE);
}
break;
case 8:
// set 8
for (int i : LitArray8) {
leds_TIMER[i + (NUM_LEDS_PER_DIGIT * DIGIT_ID )].setRGB(RED,GREEN,BLUE);
}
break;
case 9:
// set 9
for (int i : LitArray9) {
leds_TIMER[i + (NUM_LEDS_PER_DIGIT * DIGIT_ID )].setRGB(RED,GREEN,BLUE);
}
break;
}
}
// set colon
void setCOLON(int RED, int GREEN, int BLUE) {
for (int i : COLONArray) {
leds_TIMER[(i)].setRGB(RED,GREEN,BLUE);
}
}
// set all digits
void setTimeDisplay(int MINUTES, int SECONDS, int RED, int GREEN, int BLUE) {
setDIGIT(1, ((MINUTES/10)%10), RED, GREEN, BLUE);
setDIGIT(2, (MINUTES%10), RED, GREEN, BLUE);
setDIGIT(3, ((SECONDS/10)%10), RED, GREEN, BLUE);
setDIGIT(4, (SECONDS%10), RED, GREEN, BLUE);
setCOLON(RED, GREEN, BLUE);
}
void showTimeDisplay(int MINUTES, int SECONDS, int RED, int GREEN, int BLUE) {
EVERY_N_MILLISECONDS(5) {
// toggle between reading ADC data and refreshing LED strings (dunno, some artefacts appear if you do both really quickly after each other).
// leave this in here, if needed, expand the delay between executions
if (toggle) {
toggle = false;
if (prevMINUTES != MINUTES || prevSECONDS != SECONDS || prevCLOCKRED != RED || prevCLOCKGREEN != GREEN || prevCLOCKBLUE != BLUE) {
setTimeDisplay(MINUTES, SECONDS, RED, GREEN, BLUE);
FastLED.show(CLOCK_LED_BRIGHTNESS);
FastLED.clearData();
prevMINUTES = MINUTES;
prevSECONDS = SECONDS;
prevCLOCKRED = RED;
prevCLOCKGREEN = GREEN;
prevCLOCKBLUE = BLUE;
}
}
else {
toggle = true;
}
}
}

View File

@@ -0,0 +1,31 @@
void checkPIT() {
if ((digitalRead(PIT_RELEASE_PIN)) && (millis() - PITopenTimestamp >= PITopenTime)) {
digitalWrite(PIT_RELEASE_PIN, LOW);
}
}
void openPIT() {
if (!PITreleased) {
PITreleased = true;
PITopenTimestamp = millis();
digitalWrite(PIT_RELEASE_PIN, HIGH);
}
}
// usage: blink_LED_BlueTeam(<interval in milliseconds>);
void blink_LED_BlueTeam(int BLINK_INTERVAL) {
EVERY_N_MILLISECONDS(BLINK_INTERVAL) {
if (BLINK_COUNTER_BLUETEAM-- > 0) {
digitalWrite(BLUE_TEAM_LED_PIN, !digitalRead(BLUE_TEAM_LED_PIN));
}
}
}
// usage: blink_LED_RedTeam(<interval in milliseconds times two>);
void blink_LED_RedTeam(int BLINK_INTERVAL) {
EVERY_N_MILLISECONDS(BLINK_INTERVAL) {
if (BLINK_COUNTER_REDTEAM-- > 0) {
digitalWrite(RED_TEAM_LED_PIN, !digitalRead(RED_TEAM_LED_PIN));
}
}
}

View File

@@ -0,0 +1,217 @@
// ROFLS+ Arena Controller
#include <WiFi.h>
#include <esp_now.h> // automatically installed for ESP32 boards, I think?
#include <Preferences.h> // automatically installed for ESP32 boards
#include <FastLED.h> // https://fastled.io/
#include <avdweb_Switch.h> // https://github.com/avdwebLibraries/avdweb_Switch
#include <CountDown.h> // https://github.com/RobTillaart/CountDown
#include <StopWatch.h> // 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<WS2811Controller800Khz, LED_DATA_PIN_TIMER, GRB>(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);
}
}

View File