25 Commits

Author SHA1 Message Date
3d9a1a778c fixed wrong MAC addresses for clocks 2025-09-26 04:00:48 +02:00
4d7a43c9d1 added preprocessor statements to switch out MAC Addresses at compile time 2025-09-23 07:10:36 +02:00
c450cfb7c9 Changed Clock Brightness to 128, added relay 3 to be controlled by the lightswitch 2025-09-22 16:12:14 +02:00
7c3dbfab63 added additional MAC addresses for Arena B 2025-09-14 19:46:50 +02:00
fc472600c4 updated Arena Controller to support two clocks at the same time 2025-09-13 00:27:22 +02:00
649cbe63b1 updated libraries, fixed ESP-NOW send data function to work with the new library 2025-09-09 01:09:15 +02:00
79c734bd34 fixed a copy and paste error in the manual 2025-05-04 19:33:19 +02:00
3e29ab76e2 added Reference Manual, increased Clock Brightness 2025-05-04 19:26:57 +02:00
d81ab7da89 prevent Tapout while not in fight 2025-04-20 03:16:40 +02:00
5e5ff83506 prevent Team buttons being pushed in a running fight 2025-04-20 03:09:39 +02:00
606219b8bd implemented 'end screen' to be displayed when the fight timer ends. Cleaned up some comments 2025-04-19 08:48:59 +02:00
d93b283d2c shifted 'out' from the tapout screen one digit to the right 2025-04-19 06:39:17 +02:00
c9c4b1c1c5 refactored main loop, added ready countdown to unpause 2025-04-18 10:15:02 +02:00
4698dd7d42 removed unused variables 2025-04-18 08:12:44 +02:00
ee6b87399e added pit controller firmware, and changed the pit activation to send a command via ESP-Now 2025-04-18 02:36:19 +02:00
f53744c23c refactored LED Display logic to make it more readable 2025-04-16 18:42:06 +02:00
6c5586e71b implemented Team Button LEDs and tap out feature 2025-04-16 08:11:02 +02:00
70d4b3886d added preliminary implementation of Team Button LEDs 2025-04-08 09:30:22 +02:00
b82e4eb58b adjusted code to actual hardware, added 'ready' countdown 2025-04-08 04:50:44 +02:00
06a286eadd fixed remote PitHold, added persistant boardID 2025-03-03 20:41:12 +01:00
508f5f32e4 fixed wrong modulo for the display 2025-02-26 17:46:28 +01:00
4dc9ef1db7 refactored and added rumble mode, added 'pit hold by ref' 2025-02-26 16:50:57 +01:00
20fe660838 added forced start/continue, combined remote firmware 2025-02-26 06:03:32 +01:00
c2bffd7a26 removed not used code anymore from the controller firmware, added ESP-NOW functions and settings to the controller to control the display 2025-02-24 06:26:45 +01:00
9e708d461a added tap out to the display firmware, added a test firmware for sending to the display via ESP-NOW 2025-02-23 01:57:53 +01:00
14 changed files with 3789 additions and 466 deletions

View File

@@ -8,31 +8,16 @@ void pollInput (){
buttonRESET.poll();
switchRUMBLE.poll();
switchPIT.poll();
buttonREDTEAM.poll();
buttonBLUETEAM.poll();
switchLIGHT.poll();
switchTESTmode.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;
}
// only set the var if the button was actually pushed or released, to prevent overriding data from the remote
if (buttonSTART.singleClick() || buttonSTART.longPress() || buttonPAUSE.singleClick() || buttonPIT.singleClick() || buttonPIT.switched() || buttonRESET.longPress()) {
buttonSTARTvar = buttonSTART.singleClick();
buttonSTARTforced = buttonSTART.longPress();
buttonPAUSEvar = buttonPAUSE.singleClick();
buttonPITvar = buttonPIT.singleClick();
buttonPIThold = buttonPIT.on();
buttonRESETvar = buttonRESET.longPress();
}
}

View File

@@ -1,133 +0,0 @@
// 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

@@ -1,6 +1,6 @@
void checkPIT() {
if ((digitalRead(PIT_RELEASE_PIN)) && (millis() - PITopenTimestamp >= PITopenTime)) {
digitalWrite(PIT_RELEASE_PIN, LOW);
if ((digitalRead(!PIT_RELEASE_PIN)) && (millis() - PITopenTimestamp >= PITopenTime)) {
//digitalWrite(PIT_RELEASE_PIN, relayOffState);
}
}
@@ -8,24 +8,115 @@ void openPIT() {
if (!PITreleased) {
PITreleased = true;
PITopenTimestamp = millis();
digitalWrite(PIT_RELEASE_PIN, HIGH);
//digitalWrite(PIT_RELEASE_PIN, relayOnState);
sendToPitController.PIT = true;
esp_now_send(broadcastAddressPitController, (uint8_t *) &sendToPitController, sizeof(sendToPitController));
}
}
// 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));
void openPITmanually() {
PITreleased = true;
PITopenTimestamp = millis();
//digitalWrite(PIT_RELEASE_PIN, relayOnState);
sendToPitController.PIT = true;
esp_now_send(broadcastAddressPitController, (uint8_t *) &sendToPitController, sizeof(sendToPitController));
}
void arenaLIGHT() {
if (switchLIGHT.on()) {
digitalWrite(LIGHT_PIN, LOW);
digitalWrite(LIGHT_PIN2, LOW);
}
else {
digitalWrite(LIGHT_PIN, HIGH);
digitalWrite(LIGHT_PIN2, HIGH);
}
}
// 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));
void statusLEDs() {
if (!switchLIGHT.on()) {
digitalWrite(LIGHT_STATUS_LED, HIGH);
}
else {
digitalWrite(LIGHT_STATUS_LED, LOW);
}
if (switchPIT.on()) {
digitalWrite(AUTOPIT_STATUS_LED, HIGH);
}
else {
digitalWrite(AUTOPIT_STATUS_LED, LOW);
}
if (switchRUMBLE.on()) {
digitalWrite(MODE_STATUS_LED, HIGH);
}
else {
digitalWrite(MODE_STATUS_LED, LOW);
}
}
void updateTEAMLEDs() {
if ((buttonREDTEAMvar == true) && (sendToREDTEAMbutton.TEAMLED == false)) {
sendToREDTEAMbutton.TEAMLED = true;
esp_now_send(broadcastAddressREDTEAMbutton, (uint8_t *)&sendToREDTEAMbutton, sizeof(sendToREDTEAMbutton));
}
// else if ((buttonREDTEAMvar == false) && (sendToREDTEAMbutton.TEAMLED == true)) {
// sendToREDTEAMbutton.TEAMLED = false;
// esp_now_send(broadcastAddressREDTEAMbutton, (uint8_t *)&sendToREDTEAMbutton, sizeof(sendToREDTEAMbutton));
// }
if ((buttonBLUETEAMvar == true) && (sendToBLUETEAMbutton.TEAMLED == false)) {
sendToBLUETEAMbutton.TEAMLED = true;
esp_now_send(broadcastAddressBLUETEAMbutton, (uint8_t *)&sendToBLUETEAMbutton, sizeof(sendToBLUETEAMbutton));
}
// else if ((buttonBLUETEAMvar == false) && (sendToBLUETEAMbutton.TEAMLED == true)) {
// sendToBLUETEAMbutton.TEAMLED = false;
// esp_now_send(broadcastAddressBLUETEAMbutton, (uint8_t *)&sendToBLUETEAMbutton, sizeof(sendToBLUETEAMbutton));
// }
}
void REDTEAM_LED(bool STATE) {
if (STATE) {
sendToREDTEAMbutton.TEAMLED = true;
esp_now_send(broadcastAddressREDTEAMbutton, (uint8_t *)&sendToREDTEAMbutton, sizeof(sendToREDTEAMbutton));
} else {
sendToREDTEAMbutton.TEAMLED = false;
esp_now_send(broadcastAddressREDTEAMbutton, (uint8_t *)&sendToREDTEAMbutton, sizeof(sendToREDTEAMbutton));
}
}
void BLUETEAM_LED(bool STATE) {
if (STATE) {
sendToBLUETEAMbutton.TEAMLED = true;
esp_now_send(broadcastAddressBLUETEAMbutton, (uint8_t *)&sendToBLUETEAMbutton, sizeof(sendToBLUETEAMbutton));
} else {
sendToBLUETEAMbutton.TEAMLED = false;
esp_now_send(broadcastAddressBLUETEAMbutton, (uint8_t *)&sendToBLUETEAMbutton, sizeof(sendToBLUETEAMbutton));
}
}
// void blink_LED_BlueTeam() {
// EVERY_N_MILLISECONDS(BLINK_INTERVAL) {
// if (BLINK_COUNTER_BLUETEAM-- > 0) {
// if (sendToBLUETEAMbutton.TEAMLED == false) {
// sendToBLUETEAMbutton.TEAMLED = true;
// } else {
// sendToBLUETEAMbutton.TEAMLED = false;
// }
// esp_now_send(broadcastAddressBLUETEAMbutton, (uint8_t *)&sendToBLUETEAMbutton, sizeof(sendToBLUETEAMbutton));
// }
// }
// }
// void blink_LED_RedTeam() {
// EVERY_N_MILLISECONDS(BLINK_INTERVAL) {
// if (BLINK_COUNTER_REDTEAM-- > 0) {
// if (sendToREDTEAMbutton.TEAMLED == false) {
// sendToREDTEAMbutton.TEAMLED = true;
// } else {
// sendToREDTEAMbutton.TEAMLED = false;
// }
// esp_now_send(broadcastAddressREDTEAMbutton, (uint8_t *)&sendToREDTEAMbutton, sizeof(sendToREDTEAMbutton));
// }
// }
// }

View File

@@ -1,123 +1,283 @@
// ROFLS+ Arena Controller
#include <WiFi.h>
#include <esp_wifi.h> // Required for wifi_tx_info_t
#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
// set Arena, switches the MAC addresses out
// 1 = Arena A (Ant)
// 2 = Arena B (Beetle)
#define ARENA 1
// 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];
// Hardware connections
// Buttons:
#define START_BTN_PIN 1
#define PAUSE_BTN_PIN 3
#define PIT_BTN_PIN 5
#define RESET_BTN_PIN 7
// Switches:
#define RUMBLE_SWITCH_PIN 9
#define PIT_ENABLE_SWITCH_PIN 11
#define LIGHT_SWITCH_PIN 12
#define TESTmode_SWITCH_PIN 4
// LEDs:
#define LIGHT_STATUS_LED 10
#define AUTOPIT_STATUS_LED 13
#define MODE_STATUS_LED 14
// Relays:
#define PIT_RELEASE_PIN 37
#define LIGHT_PIN 39
#define LIGHT_PIN2 35
#define UNUSED_RELAY4_PIN 33
const byte relayOnState = LOW;
const byte relayOffState = HIGH;
// define buttons and switches
Switch buttonSTART = Switch(START_BTN_PIN);
//
// constructor Switch
// Parameters: byte _pin, byte PinMode = 5, bool polarity = 0, unsigned long debouncePeriod = 50, unsigned long longPressPeriod = 300, unsigned long doubleClickPeriod = 250, unsigned long deglitchPeriod = 10
Switch buttonSTART = Switch(START_BTN_PIN, INPUT_PULLUP, LOW, 50, 1000);
Switch buttonPAUSE = Switch(PAUSE_BTN_PIN);
Switch buttonPIT = Switch(PIT_BTN_PIN);
Switch buttonRESET = Switch(RESET_BTN_PIN);
Switch buttonPIT = Switch(PIT_BTN_PIN, INPUT_PULLUP, LOW, 50, 1000);
Switch buttonRESET = Switch(RESET_BTN_PIN, INPUT_PULLUP, LOW, 50, 1000);
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);
Switch switchLIGHT = Switch(LIGHT_SWITCH_PIN);
Switch switchTESTmode = Switch(TESTmode_SWITCH_PIN);
bool buttonSTARTvar = false;
bool buttonSTARTforced = false;
bool buttonPAUSEvar = false;
bool buttonPITvar = false;
bool buttonPIThold = false;
bool buttonRESETvar = false;
bool buttonREDTEAMvar = false;
bool buttonREDTEAMtapout = false;
bool buttonBLUETEAMvar = false;
bool buttonBLUETEAMtapout = 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
const long PITopenTime = 500; // default: 500 activate solenoid for 500ms
const int countdownTIME = 180; // default: 180 countdown timer length in seconds, actual countdown for the fight
const int countdownToFightTIME = 3; // default: 3 countdown timer length in seconds, "ready" countdown
const int PITreleaseTime = 90; // default: 90 automatic pit release time in seconds until end of countdown
bool countdownPAUSED = false;
CountDown FightCountDown[1];
CountDown FightCountDown(CountDown::SECONDS);
CountDown ReadyCountDown(CountDown::SECONDS);
// Rumble stopwatch
StopWatch rumbleTIME;
StopWatch rumbleTIME(StopWatch::SECONDS);
int prevMINUTES = 0;
int prevSECONDS = 0;
int prevCLOCKRED = 0;
int prevCLOCKGREEN = 0;
int prevCLOCKBLUE = 0;
int CLOCK_LED_BRIGHTNESS = 16; // 64 is okay
int CLOCK_LED_BRIGHTNESS = 128; // 64 is okay
int BLINK_COUNTER_REDTEAM = 0;
int BLINK_COUNTER_BLUETEAM = 0;
int BLINK_INTERVAL = 200;
bool ARENA_READY = true;
bool ARENA_READY = false;
bool REDTEAM_READY = false;
bool BLUETEAM_READY = false;
bool resumeFight = false;
//------------------------------------------------------------------------------------
// ESP-NOW config
// send config, Clock:
#if ARENA == 1
// A Arena
uint8_t broadcastAddressClock1[] = {0x48, 0x27, 0xE2, 0x5D, 0xB6, 0x84};
uint8_t broadcastAddressClock2[] = {0xD8, 0x3B, 0xDA, 0xC9, 0x49, 0xC6};
#elif ARENA == 2
// B Arena
uint8_t broadcastAddressClock1[] = {0xD8, 0x3B, 0xDA, 0xC8, 0xFF, 0xFA};
uint8_t broadcastAddressClock2[] = {0xD8, 0x3B, 0xDA, 0xC8, 0x95, 0x42};
#endif
// struct for clock data
typedef struct struct_message_Clock {
int sendMinutes;
int sendSeconds;
int sendREDchannel;
int sendGREENchannel;
int sendBLUEchannel;
int sendBrightness;
} struct_message_Clock;
struct_message_Clock sendClockDATA;
// send config, pilot buttons:
#if ARENA == 1
// A Arena
uint8_t broadcastAddressREDTEAMbutton[] = {0x84, 0xFC, 0xE6, 0xC7, 0x23, 0x14};
uint8_t broadcastAddressBLUETEAMbutton[] = {0x84, 0xFC, 0xE6, 0xC7, 0x1A, 0x02};
#elif ARENA == 2
// B Arena
uint8_t broadcastAddressREDTEAMbutton[] = {0xD8, 0x3B, 0xDA, 0xC8, 0x95, 0x58};
uint8_t broadcastAddressBLUETEAMbutton[] = {0xD8, 0x3B, 0xDA, 0xC8, 0x95, 0x1C};
#endif
// Structure for sending data
typedef struct struct_message_send {
bool TEAMLED; // LED state
} struct_message_send;
// Create struct_message instances for sending to both receivers
struct_message_send sendToREDTEAMbutton;
struct_message_send sendToBLUETEAMbutton;
// ESP-Now stuff for the Pit controller
#if ARENA == 1
// A Arena
uint8_t broadcastAddressPitController[] = {0x84, 0xFC, 0xE6, 0xC7, 0x19, 0xDE};
#elif ARENA == 2
// B Arena
uint8_t broadcastAddressPitController[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xB0, 0x0B};
#endif
// Test Pit controller
//uint8_t broadcastAddressPitController[] = {0x94, 0xA9, 0x90, 0x0B, 0x21, 0x64};
// Structure for sending data
typedef struct struct_message_pit {
bool PIT; // LED state
} struct_message_pit;
struct_message_pit sendToPitController;
esp_now_peer_info_t peerInfo;
// callback when data is sent
void OnDataSent(const wifi_tx_info_t *tx_info, esp_now_send_status_t status) {
Serial.print("\r\nLast Packet Send Status:\t");
Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Delivery Success" : "Delivery Fail");
}
//------------------------------------------------------------------------------------
// receive 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;
typedef struct struct_message_receive {
int boardID;
bool buttonSTART;
bool buttonSTARTforced;
bool buttonPAUSE;
bool buttonPIT;
bool buttonPIThold;
bool buttonRESET;
bool buttonREDTEAM;
bool buttonREDTEAMtapout;
bool buttonBLUETEAM;
bool buttonBLUETEAMtapout;
} struct_message_receive;
// Create a struct_message called remoteDATA
struct_message remoteDATA;
// Create a struct_message called receiveDATA
struct_message_receive receiveDATA;
// 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;
memcpy(&receiveDATA, incomingData, sizeof(receiveDATA));
// only fill the data to the right vars
switch (receiveDATA.boardID) {
case 0:
// referee remote
buttonSTARTvar = receiveDATA.buttonSTART;
buttonSTARTforced = receiveDATA.buttonSTARTforced;
buttonPAUSEvar = receiveDATA.buttonPAUSE;
buttonPITvar = receiveDATA.buttonPIT;
buttonPIThold = receiveDATA.buttonPIThold;
buttonRESETvar = receiveDATA.buttonRESET;
break;
case 1:
// RED team button
// ignore button input if in rumble mode
if (!switchRUMBLE.on()) {
// ignore button press while in fight
if (!FightCountDown.isRunning()) {
buttonREDTEAMvar = receiveDATA.buttonREDTEAM;
}
if (remoteDATA.buttonPAUSEremote) {
buttonPAUSEvar = true;
}
if (remoteDATA.buttonPITremote) {
buttonPITvar = true;
}
if (remoteDATA.buttonRESETremote) {
buttonRESETvar = true;
// ignore tapout while not in fight
if (FightCountDown.isRunning()) {
buttonREDTEAMtapout = receiveDATA.buttonREDTEAMtapout;
}
}
break;
case 2:
// BLUE team button
// ignore button input if in rumble mode
if (!switchRUMBLE.on()) {
// ignore button press while in fight
if (!FightCountDown.isRunning()) {
buttonBLUETEAMvar = receiveDATA.buttonBLUETEAM;
}
// ignore tapout while not in fight
if (FightCountDown.isRunning()) {
buttonBLUETEAMtapout = receiveDATA.buttonBLUETEAMtapout;
}
}
break;
}
}
// send data to clock:
void sendTimeDisplay(int MINUTES, int SECONDS, int RED, int GREEN, int BLUE, int BRIGHTNESS) {
// only send data if there was a change
if ((sendClockDATA.sendMinutes != MINUTES) || (sendClockDATA.sendSeconds != SECONDS) || (sendClockDATA.sendREDchannel != RED) || (sendClockDATA.sendGREENchannel != GREEN) || (sendClockDATA.sendBLUEchannel != BLUE) || (sendClockDATA.sendBrightness != BRIGHTNESS)) {
sendClockDATA.sendMinutes = MINUTES;
sendClockDATA.sendSeconds = SECONDS;
sendClockDATA.sendREDchannel = RED;
sendClockDATA.sendGREENchannel = GREEN;
sendClockDATA.sendBLUEchannel = BLUE;
sendClockDATA.sendBrightness = BRIGHTNESS;
// actually send it to first clock
esp_err_t result1 = esp_now_send(broadcastAddressClock1, (uint8_t *) &sendClockDATA, sizeof(sendClockDATA));
// actually send it to second clock
esp_err_t result2 = esp_now_send(broadcastAddressClock2, (uint8_t *) &sendClockDATA, sizeof(sendClockDATA));
}
}
// Global Vars for tap out states
bool redTapOutActive = false;
unsigned long redTapOutStartTime = 0;
int redTapOutStage = 0;
bool blueTapOutActive = false;
unsigned long blueTapOutStartTime = 0;
int blueTapOutStage = 0;
// Global Vars for Fight end
bool fightStarted = false;
bool fightEnded = false;
const int END_BLINK_COUNT = 3;
const unsigned long END_BLINK_INTERVAL = 500; // in milliseconds
int endBlinkTransitions = 0;
bool endBlinkState = false;
unsigned long lastEndBlinkTime = 0;
//------------------------------------------------------------------------------------
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 relay outputs:
pinMode(PIT_RELEASE_PIN, OUTPUT);
digitalWrite(PIT_RELEASE_PIN, relayOffState);
pinMode(LIGHT_PIN, OUTPUT);
digitalWrite(LIGHT_PIN, LOW); // have it by default on, to prevent flickering, needs a better fix tho
pinMode(LIGHT_PIN2, OUTPUT);
digitalWrite(LIGHT_PIN2, LOW); // have it by default on, to prevent flickering, needs a better fix tho
pinMode(UNUSED_RELAY4_PIN, OUTPUT);
digitalWrite(UNUSED_RELAY4_PIN, relayOffState);
// set status LED outputs:
pinMode(LIGHT_STATUS_LED, OUTPUT);
digitalWrite(LIGHT_STATUS_LED, HIGH);
pinMode(AUTOPIT_STATUS_LED, OUTPUT);
digitalWrite(AUTOPIT_STATUS_LED, LOW);
pinMode(MODE_STATUS_LED, OUTPUT);
digitalWrite(MODE_STATUS_LED, LOW);
// Set device as a Wi-Fi Station
WiFi.mode(WIFI_STA);
@@ -127,91 +287,391 @@ void setup() {
Serial.println("Error initializing ESP-NOW");
return;
}
//------------------------------------------------------------------------------------
// ESP Now send part:
// Once ESPNow is successfully Init, we will register for Send CB to
// get the status of Transmitted packet
esp_now_register_send_cb(OnDataSent);
// Register first clock peer
memcpy(peerInfo.peer_addr, broadcastAddressClock1, 6);
peerInfo.channel = 0;
peerInfo.encrypt = false;
// Add peer
if (esp_now_add_peer(&peerInfo) != ESP_OK){
Serial.println("Failed to add Clock1 peer");
return;
}
// 2) Register second clock peer
memcpy(peerInfo.peer_addr, broadcastAddressClock2, 6);
// peerInfo.channel & peerInfo.encrypt already set above
if (esp_now_add_peer(&peerInfo) != ESP_OK) {
Serial.println("Failed to add Clock2 peer");
return;
}
// send initial data (I think that doesn't work but meh...)
esp_err_t result1 = esp_now_send(broadcastAddressClock1, (uint8_t *) &sendClockDATA, sizeof(sendClockDATA));
esp_err_t result2 = esp_now_send(broadcastAddressClock2, (uint8_t *) &sendClockDATA, sizeof(sendClockDATA));
// Register Red Team Button peer
memcpy(peerInfo.peer_addr, broadcastAddressREDTEAMbutton, 6);
peerInfo.channel = 0;
peerInfo.encrypt = false;
if (esp_now_add_peer(&peerInfo) != ESP_OK) {
Serial.println("Failed to add receiver 1");
return;
}
// Register Blue Team Button peer
memcpy(peerInfo.peer_addr, broadcastAddressBLUETEAMbutton, 6);
peerInfo.channel = 0;
peerInfo.encrypt = false;
if (esp_now_add_peer(&peerInfo) != ESP_OK) {
Serial.println("Failed to add receiver 2");
return;
}
// Register Pit controller peer
memcpy(peerInfo.peer_addr, broadcastAddressPitController, 6);
peerInfo.channel = 0;
peerInfo.encrypt = false;
if (esp_now_add_peer(&peerInfo) != ESP_OK) {
Serial.println("Failed to add receiver 3");
return;
}
// Initialize both Team button LED states and pit controller state
sendToREDTEAMbutton.TEAMLED = false;
sendToBLUETEAMbutton.TEAMLED = false;
sendToPitController.PIT = false;
// reset remote button LEDs and pit
esp_now_send(broadcastAddressREDTEAMbutton, (uint8_t *)&sendToREDTEAMbutton, sizeof(sendToREDTEAMbutton));
esp_now_send(broadcastAddressBLUETEAMbutton, (uint8_t *)&sendToBLUETEAMbutton, sizeof(sendToBLUETEAMbutton));
esp_now_send(broadcastAddressPitController, (uint8_t *)&sendToPitController, sizeof(sendToPitController));
//------------------------------------------------------------------------------------
// ESP Now receive part:
// 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
// Handler for the START button logic.
void handleStartButton() {
if (buttonSTARTvar) {
buttonSTARTvar = false;
if (!FightCountDown[0].isRunning() && countdownPAUSED == false) {
if (buttonREDTEAMvar && buttonBLUETEAMvar) {
// Fresh start: no countdown is running, and the fight hasn't been paused.
if (!FightCountDown.isRunning() && !rumbleTIME.isRunning() && countdownPAUSED == false) {
if (switchRUMBLE.on()) {
buttonREDTEAMvar = false;
buttonBLUETEAMvar = false;
FightCountDown[0].start(0,0,countdownTIME,0);
ARENA_READY = true;
REDTEAM_LED(true);
BLUETEAM_LED(true);
ReadyCountDown.start(countdownToFightTIME);
}
else if (buttonREDTEAMvar && buttonBLUETEAMvar && !switchRUMBLE.on()) {
buttonREDTEAMvar = false;
buttonBLUETEAMvar = false;
ARENA_READY = true;
REDTEAM_LED(true);
BLUETEAM_LED(true);
ReadyCountDown.start(countdownToFightTIME);
}
}
else {
if (buttonREDTEAMvar && buttonBLUETEAMvar) {
// Resume (unpause) branch: instead of calling FightCountDown.resume() immediately,
// we want to display ReadyCountDown first.
if (buttonREDTEAMvar && buttonBLUETEAMvar && !switchRUMBLE.on()) {
buttonREDTEAMvar = false;
buttonBLUETEAMvar = false;
resumeFight = true; // Mark that we want to resume later.
countdownPAUSED = false;
FightCountDown[0].cont();
ARENA_READY = true;
REDTEAM_LED(true);
BLUETEAM_LED(true);
ReadyCountDown.start(countdownToFightTIME);
}
else if (switchRUMBLE.on()) {
buttonREDTEAMvar = false;
buttonBLUETEAMvar = false;
resumeFight = true;
countdownPAUSED = false;
ARENA_READY = true;
REDTEAM_LED(true);
BLUETEAM_LED(true);
ReadyCountDown.start(countdownToFightTIME);
}
}
}
// pause button logic
}
// Handler for the forced start button logic.
void handleForcedStartButton() {
if (buttonSTARTforced) {
buttonSTARTforced = false;
if (!FightCountDown.isRunning() && !rumbleTIME.isRunning() && countdownPAUSED == false) {
buttonREDTEAMvar = false;
buttonBLUETEAMvar = false;
ARENA_READY = true;
REDTEAM_LED(true);
BLUETEAM_LED(true);
ReadyCountDown.start(countdownToFightTIME);
}
else {
buttonREDTEAMvar = false;
buttonBLUETEAMvar = false;
resumeFight = true;
countdownPAUSED = false;
ARENA_READY = true;
REDTEAM_LED(true);
BLUETEAM_LED(true);
ReadyCountDown.start(countdownToFightTIME);
}
}
}
// Handler for the pause button logic.
void handlePauseButton() {
if (buttonPAUSEvar) {
buttonPAUSEvar = false;
if (FightCountDown[0].isRunning()) {
if (FightCountDown.isRunning()) {
countdownPAUSED = true;
FightCountDown[0].stop();
FightCountDown.stop();
}
if (rumbleTIME.isRunning()) {
countdownPAUSED = true;
rumbleTIME.stop();
}
}
// pit button logic
}
// Handler for the pit button logic.
void handlePitButton() {
if (buttonPITvar) {
buttonPITvar = false;
buttonPIThold = false;
openPITmanually();
}
}
// check for automatic pit release.
void handleAutoPitRelease() {
// Only release the pit if it hasn't already been released.
if (!PITreleased) {
if (FightCountDown.remaining() <= PITreleaseTime && FightCountDown.remaining() != 0 &&
!switchRUMBLE.on() && switchPIT.on() && buttonPIThold == false) {
openPIT();
}
// automatic pit release
if (FightCountDown[0].remaining() <= PITreleaseTime && FightCountDown[0].remaining() > 0 && switchPIT.on()) {
else if (rumbleTIME.elapsed() >= PITreleaseTime && switchRUMBLE.on() &&
switchPIT.on() && buttonPIThold == false) {
openPIT();
}
// reset button logic
}
}
// Handler for transitioning from ReadyCountDown to the fight (or rumble) countdown.
void handleCountdownTransition() {
if (ReadyCountDown.remaining() == 0 && ARENA_READY) {
ARENA_READY = false;
REDTEAM_LED(false);
BLUETEAM_LED(false);
if (!switchRUMBLE.on()) {
if (resumeFight) {
FightCountDown.resume(); // Resume the paused fight countdown.
resumeFight = false;
}
else {
FightCountDown.start(countdownTIME); // Fresh start.
fightStarted = true;
}
}
else if (switchRUMBLE.on()) {
// For the rumble branch, you may decide if a resume is relevant.
// Here we simply start the rumble timer as before.
rumbleTIME.start();
resumeFight = false;
}
}
}
// The display update logic now considers all conditions in order.
void updateDisplay() {
if (ReadyCountDown.isRunning()) {
// Display Ready Countdown in Yellow
sendTimeDisplay((ReadyCountDown.remaining()/60 % 60), (ReadyCountDown.remaining()%60), 255, 165, 0, CLOCK_LED_BRIGHTNESS);
} else if (switchRUMBLE.on()) {
// Display the Rumble Timer
sendTimeDisplay((rumbleTIME.elapsed()/60 % 60), (rumbleTIME.elapsed()%60), 0, 255, 255, CLOCK_LED_BRIGHTNESS);
} else if (!FightCountDown.isRunning() && !countdownPAUSED) {
// Choose green if both team buttons are active; otherwise, choose magenta.
if (buttonREDTEAMvar && buttonBLUETEAMvar) {
sendTimeDisplay((countdownTIME/60 % 60), (countdownTIME%60), 0, 255, 0, CLOCK_LED_BRIGHTNESS);
} else {
sendTimeDisplay((countdownTIME/60 % 60), (countdownTIME%60), 255, 0, 255, CLOCK_LED_BRIGHTNESS);
}
} else {
// choose yellow if countdown is paused and both teams aren't ready
if (countdownPAUSED && (!buttonREDTEAMvar || !buttonBLUETEAMvar)) {
sendTimeDisplay((FightCountDown.remaining()/60 % 60), (FightCountDown.remaining()%60), 255, 165, 0, CLOCK_LED_BRIGHTNESS);
} else {
// Display the countdown in green
sendTimeDisplay((FightCountDown.remaining()/60 % 60), (FightCountDown.remaining()%60), 0, 255, 0, CLOCK_LED_BRIGHTNESS);
}
}
}
// endless cycling for Red Team tap-out.
void handleRedTapOut() {
// When the red tap-out is first triggered.
if (!redTapOutActive && buttonREDTEAMtapout && !switchRUMBLE.on() && !blueTapOutActive) {
buttonREDTEAMtapout = false;
countdownPAUSED = true;
FightCountDown.stop();
REDTEAM_LED(true);
redTapOutActive = true;
redTapOutStartTime = millis();
}
// If tap-out is active, continuously update the display in a cycle.
if (redTapOutActive) {
// Define a full cycle period of 8'000 ms.
const unsigned long cycleDuration = 8000;
// Compute how far into the current cycle we are.
unsigned long cycleTime = (millis() - redTapOutStartTime) % cycleDuration;
if (cycleTime < 1500) {
// Stage 1 (0 - 1500ms): Display first tap-out message.
sendTimeDisplay(99, 0, 255, 0, 0, CLOCK_LED_BRIGHTNESS);
}
else if (cycleTime < 3000) {
// Stage 2 (1500 - 3000ms): Display second tap-out message.
sendTimeDisplay(0, 99, 255, 0, 0, CLOCK_LED_BRIGHTNESS);
}
else {
// Stage 3 (3000 - 10'000ms): Show the remaining fight countdown.
sendTimeDisplay((FightCountDown.remaining() / 60 % 60), (FightCountDown.remaining() % 60), 255, 0, 0, CLOCK_LED_BRIGHTNESS);
}
}
}
// endless cycling for Blue Team tap-out.
void handleBlueTapOut() {
// When the blue tap-out is first triggered.
if (!blueTapOutActive && buttonBLUETEAMtapout && !switchRUMBLE.on() && !redTapOutActive) {
buttonBLUETEAMtapout = false;
countdownPAUSED = true;
FightCountDown.stop();
BLUETEAM_LED(true);
blueTapOutActive = true;
blueTapOutStartTime = millis();
}
// If tap-out is active, continuously update the display in a cycle.
if (blueTapOutActive) {
// Define a full cycle period of 8'000 ms.
const unsigned long cycleDuration = 8000;
// Compute the cycle progress.
unsigned long cycleTime = (millis() - blueTapOutStartTime) % cycleDuration;
if (cycleTime < 1500) {
// Stage 1 (0 - 1500ms): Display first tap-out message.
sendTimeDisplay(99, 0, 0, 0, 255, CLOCK_LED_BRIGHTNESS);
}
else if (cycleTime < 3000) {
// Stage 2 (1500 - 3000ms): Display second tap-out message.
sendTimeDisplay(0, 99, 0, 0, 255, CLOCK_LED_BRIGHTNESS);
}
else {
// Stage 3 (3000 - 10'000ms): Show the remaining fight countdown.
sendTimeDisplay((FightCountDown.remaining() / 60 % 60), (FightCountDown.remaining() % 60), 0, 0, 255, CLOCK_LED_BRIGHTNESS);
}
}
}
void handleFightEnd() {
// When the countdown hits 0 and the fight had started, mark it as ended.
if ((FightCountDown.remaining() == 0) && fightStarted) {
fightEnded = true;
}
// Only do blinking if the fight has ended.
if (!fightEnded) {
return; // Skip the rest until fightEnded becomes true.
}
// Each full blink cycle includes an "on" and "off" state.
// Therefore, we count transitions: total transitions = END_BLINK_COUNT * 2.
const int totalTransitions = END_BLINK_COUNT * 2 + 1;
// If we haven't completed our full blink sequence, manage timing:
if (endBlinkTransitions < totalTransitions) {
unsigned long currentMillis = millis();
if (currentMillis - lastEndBlinkTime >= END_BLINK_INTERVAL) {
endBlinkState = !endBlinkState; // Toggle between on and off states.
endBlinkTransitions++; // Count this toggle.
lastEndBlinkTime = currentMillis; // Reset the timer.
}
// Depending on the blink state, update the display.
// When endBlinkState is true, use the normal brightness.
// When false, replace CLOCK_LED_BRIGHTNESS with 0 to blank the display.
if (endBlinkState) {
sendTimeDisplay(0, 0, 255, 165, 0, CLOCK_LED_BRIGHTNESS);
} else {
sendTimeDisplay(0, 0, 255, 165, 0, 0);
}
} else {
// After completing the blink sequence, ensure that the display remains on.
sendTimeDisplay(0, 0, 255, 165, 0, CLOCK_LED_BRIGHTNESS);
}
}
//----------------------------------------------------------------------------------------
void loop() {
// Poll and update low-level I/O and LEDs.
pollInput();
checkPIT();
arenaLIGHT();
statusLEDs();
updateTEAMLEDs();
// Process button events.
handleStartButton();
handleForcedStartButton();
handlePauseButton();
handlePitButton();
handleAutoPitRelease();
// Process tap-out sequences.
if (!switchRUMBLE.on()) {
handleRedTapOut();
handleBlueTapOut();
}
// Handle reset
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);
}
// Transition from ReadyCountDown to the appropriate fight countdown.
handleCountdownTransition();
// 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);
// End display
handleFightEnd();
// When no team is in a tapout sequence and fight hasn't ended, update the display.
if (!redTapOutActive && !blueTapOutActive && !fightEnded) {
updateDisplay();
}
}

View File

@@ -23,6 +23,12 @@ const int LitArray9 [] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,2
// colon
const int COLONArray [] = {224,225,226,227,228,229,230,231};
// tap out
const int LitArrayTap [] = {0,1,2,3,4,5,6,7,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151};
//const int LitArrayOut [] = {0,1,2,3,4,5,6,7,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159};
const int LitArrayOut [] = {56,57,58,59,60,61,62,63,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215};
// 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) {
@@ -98,14 +104,23 @@ void setCOLON(int RED, int GREEN, int BLUE) {
}
}
void showTimeDisplay(int MINUTES, int SECONDS, int RED, int GREEN, int BLUE, int BRIGHTNESS) {
// set all digits
if (MINUTES == 99) {
for (int i : LitArrayTap) {
leds_TIMER[i].setRGB(RED,GREEN,BLUE);
}
} else if (SECONDS == 99) {
for (int i : LitArrayOut) {
leds_TIMER[i].setRGB(RED,GREEN,BLUE);
}
} else {
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);
}
// actually display the digits
FastLED.show(BRIGHTNESS);
// clear the arrays

View File

@@ -1,6 +1,10 @@
// ROFLS+ Arena Controller
// MAC address of the MCU:
// 48:27:E2:50:86:84
#include <WiFi.h>
#include <esp_wifi.h> // Required for wifi_tx_info_t
#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/
@@ -27,12 +31,13 @@ typedef struct struct_message {
int receiveBrightness;
} struct_message;
// Create a struct_message called remoteDATA
// Create a struct_message called receiveDATA
struct_message receiveDATA;
// callback function that will be executed when data is received
void OnDataRecv(const uint8_t * mac, const uint8_t *incomingData, int len) {
memcpy(&receiveDATA, incomingData, sizeof(receiveDATA));
showTimeDisplay(receiveDATA.receiveMinutes, receiveDATA.receiveSeconds, receiveDATA.receiveREDchannel, receiveDATA.receiveGREENchannel, receiveDATA.receiveBLUEchannel, receiveDATA.receiveBrightness);
}
void setup() {
@@ -51,21 +56,16 @@ void setup() {
// 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.addLeds<WS2811Controller800Khz, LED_DATA_PIN_TIMER, GRB>(leds_TIMER, NUM_LEDS_TIMER); // GRB ordering is typical
FastLED.addLeds<WS2812B, 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
FastLED.setMaxPowerInVoltsAndMilliamps(5,4000); // Limit to 20W of output power
// set default values
receiveDATA.receiveMinutes = 12;
receiveDATA.receiveSeconds = 34;
receiveDATA.receiveREDchannel = 128;
receiveDATA.receiveGREENchannel = 128;
receiveDATA.receiveBLUEchannel = 128;
receiveDATA.receiveBrightness = 16;
// default screen, just to show it's up and running but hasn't received any data, should display 00:00 in blue
showTimeDisplay(0, 0, 0, 0, 255, 32);
}
void loop() {
// update the LED Display
showTimeDisplay(receiveDATA.receiveMinutes, receiveDATA.receiveSeconds, receiveDATA.receiveREDchannel, receiveDATA.receiveGREENchannel, receiveDATA.receiveBLUEchannel, receiveDATA.receiveBrightness);
// showTimeDisplay(12, 34, 150, 0, 150, 16);
// nothing to see here, everything get's handled by the callback function
}

View File

@@ -0,0 +1,78 @@
// Pit controller
#include <WiFi.h>
#include <esp_now.h>
#include <ESP32Servo.h>
// Define the pins for the two servos
#define SERVO1_PIN 9
#define SERVO2_PIN 7
// Define pulse widths (in microseconds)
#define DEFAULT_PULSE 2000 // Default position
#define ACTUATED_PULSE 1000 // Actuated position
// Define the reset time in milliseconds
#define RESET_TIME_MS 1000
// Create two Servo objects for the two servos
Servo servo1;
Servo servo2;
// Global variables to manage servo reset timing
volatile bool servoActuated = false; // Tracks if servos are currently actuated
unsigned long actuatedTimestamp = 0; // Stores the time when the servos were actuated
// Updated ESPNow receive callback function with the correct signature
void OnDataRecv(const esp_now_recv_info_t *recv_info, const uint8_t *incomingData, int len) {
// We expect one boolean (1 byte)
bool command = false;
if (len == sizeof(command)) {
memcpy(&command, incomingData, sizeof(command));
if (command) {
// Actuate both servos to the actuated position
servo1.writeMicroseconds(ACTUATED_PULSE);
servo2.writeMicroseconds(ACTUATED_PULSE);
// Record the time when the servos were actuated
actuatedTimestamp = millis();
servoActuated = true;
} else {
// Immediately reset both servos to the default position
servo1.writeMicroseconds(DEFAULT_PULSE);
servo2.writeMicroseconds(DEFAULT_PULSE);
servoActuated = false;
}
}
}
void setup() {
// Initialize WiFi in station mode (required for ESPNow)
WiFi.mode(WIFI_STA);
// Attach the servos to their respective pins and set to default position
servo1.attach(SERVO1_PIN);
servo2.attach(SERVO2_PIN);
servo1.writeMicroseconds(DEFAULT_PULSE);
servo2.writeMicroseconds(DEFAULT_PULSE);
// Initialize ESPNow
if (esp_now_init() != ESP_OK) {
// Optionally handle initialization errors
return;
}
// Register the ESPNow receive callback function
esp_now_register_recv_cb(OnDataRecv);
}
void loop() {
// Check if the servos are in the actuated state and if RESET_TIME_MS has elapsed
if (servoActuated && (millis() - actuatedTimestamp >= RESET_TIME_MS)) {
// Reset both servos back to the default position after the delay
servo1.writeMicroseconds(DEFAULT_PULSE);
servo2.writeMicroseconds(DEFAULT_PULSE);
servoActuated = false;
}
// Yield a little time for other tasks
delay(10);
}

View File

@@ -6,17 +6,23 @@ void pollInput (){
buttonPAUSE.poll();
buttonPIT.poll();
buttonRESET.poll();
buttonTEAM.poll();
if (buttonSTART.pushed()) {
buttonSTARTvar = true;
}
if (buttonPAUSE.pushed()) {
buttonPAUSEvar = true;
}
if (buttonPIT.pushed()) {
buttonPITvar = true;
}
if (buttonRESET.pushed()) {
buttonRESETvar = true;
// only set the var if the button was actually pushed or released, to prevent overriding data from the controller
if (buttonSTART.singleClick() || buttonSTART.longPress() || buttonPAUSE.singleClick() || buttonPIT.singleClick() || buttonPIT.switched() || buttonRESET.longPress() || buttonTEAM.singleClick() || buttonTEAM.longPress()) {
sendDATAvar = true;
buttonSTARTvar = buttonSTART.singleClick();
buttonSTARTforced = buttonSTART.longPress();
buttonPAUSEvar = buttonPAUSE.singleClick();
buttonPITvar = buttonPIT.singleClick();
buttonPIThold = buttonPIT.on();
buttonRESETvar = buttonRESET.longPress();
if (boardID == 1) {
buttonREDTEAMvar = buttonTEAM.singleClick();
buttonREDTEAMtapout = buttonTEAM.longPress();
} else if (boardID == 2) {
buttonBLUETEAMvar = buttonTEAM.singleClick();
buttonBLUETEAMtapout = buttonTEAM.longPress();
}
}
}

View File

@@ -1,59 +1,131 @@
// ROFLS+ Referee Remote
#include <WiFi.h>
#include <esp_wifi.h> // Required for wifi_tx_info_t
#include <esp_now.h> // automatically installed for ESP32 boards, I think?
#include <Preferences.h> // automatically installed for ESP32 boards
#include <avdweb_Switch.h> // https://github.com/avdwebLibraries/avdweb_Switch
// set board ID
// This is only needed for the initial flashing, as it writes the ID in to the ESPs internal flash
//
// 0 = referee remote
// 1 = Red Team Button
// 2 = Blue Team Button
const bool writeBoardID = false;
int boardID = 1;
// set Arena, switches the MAC addresses out
// 1 = Arena A (Ant)
// 2 = Arena B (Beetle)
#define ARENA 1
// Hardware connections
#define START_BTN_PIN 4
#define PAUSE_BTN_PIN 3
#define PIT_BTN_PIN 2
#define RESET_BTN_PIN 1
#define START_BTN_PIN 10
#define PAUSE_BTN_PIN 8
#define PIT_BTN_PIN 1
#define RESET_BTN_PIN 3
#define TEAM_BTN_PIN 16
#define TEAM_LED_PIN 17
// define buttons and switches
Switch buttonSTART = Switch(START_BTN_PIN);
Switch buttonSTART = Switch(START_BTN_PIN, INPUT_PULLUP, LOW, 50, 1000);
Switch buttonPAUSE = Switch(PAUSE_BTN_PIN);
Switch buttonPIT = Switch(PIT_BTN_PIN);
Switch buttonRESET = Switch(RESET_BTN_PIN);
Switch buttonPIT = Switch(PIT_BTN_PIN, INPUT_PULLUP, LOW, 50, 1000);
Switch buttonRESET = Switch(RESET_BTN_PIN, INPUT_PULLUP, LOW, 50, 1000);
Switch buttonTEAM = Switch(TEAM_BTN_PIN, INPUT_PULLUP, LOW, 50, 1000);
bool buttonSTARTvar = false;
bool buttonSTARTforced = false;
bool buttonPAUSEvar = false;
bool buttonPITvar = false;
bool buttonPIThold = false;
bool buttonRESETvar = false;
bool buttonREDTEAMvar = false;
bool buttonREDTEAMtapout = false;
bool buttonBLUETEAMvar = false;
bool buttonBLUETEAMtapout = false;
bool sendDATA = false;
bool sendDATAvar = false;
// ESP-NOW config
// REPLACE WITH YOUR RECEIVER MAC Address
#if ARENA == 1
// A Arena Controller MAC Address
uint8_t broadcastAddress[] = {0x84, 0xFC, 0xE6, 0xC7, 0x1A, 0x8C};
#elif ARENA == 2
// B Arena Controller MAC Address
uint8_t broadcastAddress[] = {0xD8, 0x3B, 0xDA, 0xC9, 0x0C, 0xEE};
#endif
// Structure example to send data
// Must match the receiver structure
typedef struct struct_message {
bool buttonSTARTremote;
bool buttonPAUSEremote;
bool buttonPITremote;
bool buttonRESETremote;
} struct_message;
typedef struct struct_message_send {
int boardID;
bool buttonSTART;
bool buttonSTARTforced;
bool buttonPAUSE;
bool buttonPIT;
bool buttonPIThold;
bool buttonRESET;
bool buttonREDTEAM;
bool buttonREDTEAMtapout;
bool buttonBLUETEAM;
bool buttonBLUETEAMtapout;
} struct_message_send;
// Create a struct_message called myData
struct_message remoteDATA;
struct_message_send sendDATA;
// Add struct for receiving ESP-NOW data
typedef struct struct_message_receive {
bool TEAMLED; // Boolean to control the team LED
} struct_message_receive;
// Create instance for receiving ESP-NOW data
struct_message_receive receiveDATA;
esp_now_peer_info_t peerInfo;
Preferences preferences;
// callback when data is sent
/*
void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) {
void OnDataSent(const wifi_tx_info_t *tx_info, esp_now_send_status_t status) {
Serial.print("\r\nLast Packet Send Status:\t");
Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Delivery Success" : "Delivery Fail");
}
*/
// Callback function for receiving ESP-NOW data
void OnDataReceive(const esp_now_recv_info *recv_info, const uint8_t *incomingData, int len) {
// Copy the received data into the struct
memcpy(&receiveDATA, incomingData, sizeof(receiveDATA));
// Update the LED state based on received data
digitalWrite(TEAM_LED_PIN, receiveDATA.TEAMLED ? HIGH : LOW);
}
void setup() {
Serial.begin(115200);
// write boardID to internal Flash if needed
if (writeBoardID) {
// open preferences, namespace, RW mode = false
preferences.begin("Arena-remote", false);
preferences.putUInt("boardID", boardID);
} else {
// open preferences, namespace, RO mode = true
preferences.begin("Arena-remote", true);
}
// read board ID from internal flash
boardID = preferences.getUInt("boardID", 0);
preferences.end();
// configure and set the LED output pin
pinMode(TEAM_LED_PIN, OUTPUT);
digitalWrite(TEAM_LED_PIN, LOW);
// Set device as a Wi-Fi Station
WiFi.mode(WIFI_STA);
@@ -63,8 +135,8 @@ void setup() {
return;
}
// Once ESPNow is successfully Init, we will register for Send CB to
// get the status of Trasnmitted packet
//esp_now_register_send_cb(OnDataSent);
// get the status of Transmitted packet
esp_now_register_send_cb(OnDataSent);
// Register peer
memcpy(peerInfo.peer_addr, broadcastAddress, 6);
@@ -75,69 +147,54 @@ void setup() {
Serial.println("Failed to add peer");
return;
}
// Register receive callback
esp_now_register_recv_cb(OnDataReceive);
// populate sendDATA struct with some data:
sendDATA.boardID = boardID;
sendDATA.buttonSTART = false;
sendDATA.buttonSTARTforced = false;
sendDATA.buttonPAUSE = false;
sendDATA.buttonPIT = false;
sendDATA.buttonPIThold = false;
sendDATA.buttonRESET = false;
sendDATA.buttonREDTEAM = false;
sendDATA.buttonREDTEAMtapout = false;
sendDATA.buttonBLUETEAM = false;
sendDATA.buttonBLUETEAMtapout = false;
}
void sendDATA_to_controller() {
// if ((sendDATA.buttonSTART != buttonSTARTvar) || (sendDATA.buttonSTARTforced != buttonSTARTforced) || (sendDATA.buttonPAUSE !=buttonPAUSEvar) || (sendDATA.buttonPIT != buttonPITvar) || (sendDATA.buttonPIThold != buttonPIThold) || (sendDATA.buttonRESET != buttonRESETvar) || (sendDATA.buttonREDTEAM != buttonREDTEAMvar) || (sendDATA.buttonREDTEAMtapout != buttonREDTEAMtapout) || (sendDATA.buttonBLUETEAM != buttonBLUETEAMvar) || (sendDATA.buttonBLUETEAMtapout != buttonBLUETEAMtapout)) {
if (sendDATAvar) {
sendDATAvar = false;
// prepare sendDATA data
sendDATA.boardID = boardID;
sendDATA.buttonSTART = buttonSTARTvar;
sendDATA.buttonSTARTforced = buttonSTARTforced;
sendDATA.buttonPAUSE = buttonPAUSEvar;
sendDATA.buttonPIT = buttonPITvar;
sendDATA.buttonPIThold = buttonPIThold;
sendDATA.buttonRESET = buttonRESETvar;
sendDATA.buttonREDTEAM = buttonREDTEAMvar;
sendDATA.buttonREDTEAMtapout = buttonREDTEAMtapout;
sendDATA.buttonBLUETEAM = buttonBLUETEAMvar;
sendDATA.buttonBLUETEAMtapout = buttonBLUETEAMtapout;
// send data
esp_err_t result = esp_now_send(broadcastAddress, (uint8_t *) &sendDATA, sizeof(sendDATA));
// check if transmission was successfull
// if (result == ESP_OK) {
// Serial.println("Sent with success");
// }
// else {
// Serial.println("Error sending the data");
// }
}
}
void loop() {
// poll all the switch/button inputs
pollInput();
// start button logic
if (buttonSTARTvar) {
buttonSTARTvar = false;
remoteDATA.buttonSTARTremote = true;
sendDATA = true;
}
// pause button logic
if (buttonPAUSEvar) {
buttonPAUSEvar = false;
remoteDATA.buttonPAUSEremote = true;
sendDATA = true;
}
// pit button logic
if (buttonPITvar) {
buttonPITvar = false;
remoteDATA.buttonPITremote = true;
sendDATA = true;
}
// reset button logic
if (buttonRESETvar) {
buttonRESETvar = false;
remoteDATA.buttonRESETremote = true;
sendDATA = true;
}
// Set values to send
//remoteDATA.buttonSTARTremote = false;
//remoteDATA.buttonPAUSEremote = false;
//remoteDATA.buttonPITremote = false;
//remoteDATA.buttonRESETremote = false;
// Send message via ESP-NOW
//esp_err_t result = esp_now_send(broadcastAddress, (uint8_t *) &remoteDATA, sizeof(remoteDATA));
if (sendDATA == true) {
esp_err_t result = esp_now_send(broadcastAddress, (uint8_t *) &remoteDATA, sizeof(remoteDATA));
sendDATA = false;
// clear remoteDATA struct
remoteDATA.buttonSTARTremote = false;
remoteDATA.buttonPAUSEremote = false;
remoteDATA.buttonPITremote = false;
remoteDATA.buttonRESETremote = false;
if (result == ESP_OK) {
Serial.println("Sent with success");
}
else {
Serial.println("Error sending the data");
}
}
/*
if (result == ESP_OK) {
Serial.println("Sent with success");
}
else {
Serial.println("Error sending the data");
}
*/
//delay(2000);
sendDATA_to_controller();
}

80
Reference_Manual.md Normal file
View File

@@ -0,0 +1,80 @@
# ROFLS Arena Reference Manual
### Before a fight/tournament (omit step 1-6 after initial setup):
1. Check all connections
2. Power on the PSU
3. Turn on the Teambuttons and the Referee Remote
4. Wait for the 7 Segment Clock to turn on (~2s)
5. Turn on the lights (if off and needed)
6. Open the Controller Box and set the brightness with the potentiometer on the top right
7. Select the mode (explanations for the modes, see below):
8. Press and Hold Reset for >1s, can be on the Controller itself or the Referee Remote
9. Arena is ready
### Start a normal fight:
1. for good measure: Press and Hold Reset for >1s, can be on the Controller itself or the Referee Remote.
2. Team Red and Team Blue need to (short) press their respective Teambuttons, the Clock turns green to signal that both are ready.
3. Press Start, if the Teambuttons are not working, the Start button can be long pressed (>1s), to force a start.
4. To prevent the automatic pit opening, press and hold the Pit button, as soon as the pit button gets released, the pit will open.
### Start a rumble fight:
1. for good measure: Press and Hold Reset for >1s, can be on the Controller itself or the Referee Remote.
2. Press Start
3. To prevent the automatic pit opening, press and hold the Pit button, as soon as the pit button gets released, the pit will open.
### Pausing a running fight:
1. Press the Pause button
2. To resume:
- normal fight:
Both Teams need to press their respective Teambuttons to signal that they are both ready.
- Press start, after 3s, the timer resumes.
- rumble fight:
- Press start, after 3s, the stop watch resumes.
## Modes
* Normal Mode:
* Normal fight mode, 3 Minute Timer, Tapout enabled, after 90s (halftime) automatic pit opening (if enabled)
* Teambuttons are active and need to be pressed once to sign that they are ready. They light up if ready.
* Teambuttons LEDs turn of when the fight starts
* During a running fight, if one of the Teambuttons is pressed >1s, it counts as a tapout. The Timer stops and displays "TAPOUT", cycles between "TAPOUT" and the end time.
* Can be paused, resuming works the same as starting, Teams must be ready
* Rumble Mode:
* Rumble mode, stop watch counting up, Tapout disabled, after 90s automatic pit opening (if enabled)
* Match starts 3s after pressing start
* Teambuttons are inactive
* Teambutton LEDs Light up 3s before the match begins, and turn off when it starts.
* No Tapout available
* Can be paused, resuming works the same as starting, Teams must be ready
## Buttons explained
> The 4 buttons on the referee remote and the controller box have the same function and can both be used.
* Start
* Starts a fight, can be long pressed (>1s) to force start a fight
* Pause
* Pauses a fight
* Pit
* Short press (<1s) immediately opens the pit, Long press (>1s) prevents the pit from automatically open, but opens immediately after released
* Reset
* Resets the Arena Controller, needs to be long pressed (>1s)
* Lights Switch
* Turns on/off the Arena Lights, lights up if lights are on.
* Auto Pit Switch
* Turn on/off the automatic pit opening, lights up if enabled
* Mode Switch
* R = Rumble mode
* N = Normal mode
* T = Self Test (not implemented yet)
## Display Colours & Status explained
| Colour | Meaning |
|--------|---------|
| Blue with one purple segment, displaying 00:00 | not initialized (hit reset to fix) |
| Purple, displaying 03:00 | Normal Mode, Idle/Arena Ready |
| Green | Normal Mode, Both Teams Ready/Running Fight |
| Yellow | 3s Ready Countdown or Paused |
| Yellow, initally blinking 3 times | Timer run out / finish |
| Red, cycling between tap, out and time | Red Team has tapped out |
| Blue, cycling between tap, out and time | Blue Team has tapped out |
| Teal, displaying 00:00 | Rumble mode, Idle/Arena Ready |
| Teal, displaying timer | Rumble mode, active fight |

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,106 @@
// 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 <CountDown.h> // https://github.com/RobTillaart/CountDown
#include <StopWatch.h> // https://github.com/RobTillaart/StopWatch_RT
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 CLOCK_LED_BRIGHTNESS = 16; // 64 is okay
// REPLACE WITH YOUR RECEIVER MAC Address
uint8_t broadcastAddress[] = {0x48, 0x27, 0xE2, 0x5D, 0xB6, 0x84};
// ESP-NOW config
// Structure example to send data
// Must match the receiver structure
typedef struct struct_message {
int sendMinutes;
int sendSeconds;
int sendREDchannel;
int sendGREENchannel;
int sendBLUEchannel;
int sendBrightness;
} struct_message;
// Create a struct_message called remoteDATA
struct_message sendDATA;
esp_now_peer_info_t peerInfo;
// callback when data is sent
void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) {
Serial.print("\r\nLast Packet Send Status:\t");
Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Delivery Success" : "Delivery Fail");
}
void setup() {
// 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 Send CB to
// get the status of Trasnmitted packet
esp_now_register_send_cb(OnDataSent);
// Register peer
memcpy(peerInfo.peer_addr, broadcastAddress, 6);
peerInfo.channel = 0;
peerInfo.encrypt = false;
// Add peer
if (esp_now_add_peer(&peerInfo) != ESP_OK){
Serial.println("Failed to add peer");
return;
}
// set rumble stopwatch resolution to seconds
esp_err_t result = esp_now_send(broadcastAddress, (uint8_t *) &sendDATA, sizeof(sendDATA));
sendDATA.sendMinutes = 88;
sendDATA.sendSeconds = 88;
sendDATA.sendREDchannel = 63;
sendDATA.sendGREENchannel = 0;
sendDATA.sendBLUEchannel = 0;
sendDATA.sendBrightness = 32;
}
void loop() {
esp_err_t result = esp_now_send(broadcastAddress, (uint8_t *) &sendDATA, sizeof(sendDATA));
sendDATA.sendMinutes = 88;
sendDATA.sendSeconds = 88;
sendDATA.sendREDchannel = 63;
sendDATA.sendGREENchannel = 0;
sendDATA.sendBLUEchannel = 0;
sendDATA.sendBrightness = 32;
delay(2000);
// if (result == ESP_OK) {
// Serial.println("Sent with success");
// }
// else {
// Serial.println("Error sending the data");
// }
//showTimeDisplay((FightCountDown[0].remaining()/60%10), (FightCountDown[0].remaining()%60), 0, XDAS, 0);
}

View File

@@ -1,35 +0,0 @@
/// @file Blink.ino
/// @brief Blink the first LED of an LED strip
/// @example Blink.ino
#include <FastLED.h>
// How many leds in your strip?
#define NUM_LEDS 3
// For led chips like WS2812, which have a data line, ground, and power, you just
// need to define DATA_PIN. For led chipsets that are SPI based (four wires - data, clock,
// ground, and power), like the LPD8806 define both DATA_PIN and CLOCK_PIN
// Clock pin only needed for SPI based chipsets when not using hardware SPI
#define DATA_PIN 3
//#define CLOCK_PIN 13
// Define the array of leds
CRGB leds[NUM_LEDS];
#define POTI_PIN 2
int POTI_VALUE = 0;
void setup() {
FastLED.addLeds<WS2812, DATA_PIN, GRB>(leds, NUM_LEDS); // GRB ordering is typical
}
void loop() {
leds[0] = CRGB::Red;
leds[1] = CRGB::Blue;
leds[2] = CRGB::Green;
FastLED.setBrightness(map(analogRead(POTI_PIN), 0, 8191, 8, 255));
FastLED.show();
delay(1);
//POTI_VALUE = map(analogRead(POTI_PIN), 0, 8191, 0, 255);
}