#include #include #include #include #include #ifdef __AVR__ #include #endif // Analog input for piezo #define TARGETPIN A0 // How long to disable the target after impact #define LOCKOUT 100 // Minimum ADC reading to count as an impact #define NOISE 100 //The GPIO pin for the WS2812 leds #define DATA_PIN 14 // Total number of leds on the string #define NUM_LEDS 8 // How many attempts to make in the WiFi connect loop before retrying //#define WIFI_RETRY_COUNT 15 // How many ms to delay between ADC reads (too fast might crash the ESP) #define ADC_READ_DELAY 10 // Game name to number maps #define ALL 0 #define AROUND 1 #define BLACKOUT 2 #define MOLE 3 //we expect this to be written at 0, or we'll format. #define EEPROM_MAGIC_ID 138 // The server's AP name const char* AP_NAME = "RECOIL"; // AP password const char* AP_PASS = ""; // websocket client to update the server of our status WebSocketsClient webSocket; // FastLED used for WS2812 CRGB leds[NUM_LEDS]; // These are the defaults but can be changed by any web scoreboard uint8_t currentGame = ALL; uint8_t moleDelay = 4; uint8_t gameEnabled = 1; uint32_t clientColor; String clientName; uint32_t lastUpdate; uint32_t lastAnalogRead; void switchGame() { Serial.println("SWITCH GAME EVENT"); if (currentGame == ALL) { gameEnabled = 1; fill_solid(leds, NUM_LEDS, clientColor); FastLED.show(); } else if (currentGame == AROUND) { gameEnabled = 0; fill_solid(leds, NUM_LEDS, CRGB::Black); FastLED.show(); } else if (currentGame == BLACKOUT) { gameEnabled = 1; fill_solid(leds, NUM_LEDS, clientColor); FastLED.show(); } else if (currentGame == MOLE) { gameEnabled = 0; fill_solid(leds, NUM_LEDS, CRGB::Black); FastLED.show(); } } void webSocketEvent(WStype_t type, uint8_t * payload, size_t length) { switch(type) { case WStype_DISCONNECTED: { Serial.printf("[WSc] Disconnected!\r\n"); for (int i=0; i < 3; i++) { fill_solid(leds, NUM_LEDS, CRGB::Black); FastLED.show(); delay(300); fill_solid(leds, NUM_LEDS, CRGB::Red); FastLED.show(); delay(300); } } break; case WStype_CONNECTED: { Serial.printf("[WSc] Connected to url: %s\r\n", payload); // send message to server when Connected for (int i=0; i < 3; i++) { fill_solid(leds, NUM_LEDS, CRGB::Black); FastLED.show(); delay(300); fill_solid(leds, NUM_LEDS, CRGB::Green); FastLED.show(); delay(300); } webSocket.sendTXT(buildRegister()); fill_solid(leds, NUM_LEDS, clientColor); FastLED.show(); } break; case WStype_TEXT: Serial.printf("[WSc] get text: %s\r\n", payload); if (payload[0] == 'C') { // color update event Serial.println("COLOR UPDATE..."); char cPayload[length]; memcpy(cPayload, payload, length); String id; String color; Serial.println(cPayload); int i = 1; while (cPayload[i] != 'I') { id += cPayload[i]; i++; } i++; while (cPayload[i] != '*') { color += cPayload[i]; i++; } Serial.println(id); Serial.println(color); if (id.toInt() == ESP.getChipId()) { Serial.println("This is us."); clientColor = color.toInt(); writeEEPROM(); for (int i=0; i < 3; i++) { fill_solid(leds, NUM_LEDS, CRGB::Black); FastLED.show(); delay(300); fill_solid(leds, NUM_LEDS, clientColor); FastLED.show(); delay(300); } Serial.print("Our name is "); Serial.println(clientName); if (!gameEnabled) { fill_solid(leds, NUM_LEDS, CRGB::Black); FastLED.show(); } } else { Serial.println("This is not us."); } } else if (payload[0] == 'N') { //name update event Serial.println("NAME UPDATE..."); char cPayload[length]; memcpy(cPayload, payload, length); String id; String name; Serial.println(cPayload); int i = 1; while (cPayload[i] != 'I') { id += cPayload[i]; i++; } i++; while (cPayload[i] != '*') { name += cPayload[i]; i++; } Serial.println(id); Serial.println(name); if (id.toInt() == ESP.getChipId()) { Serial.println("This is us."); clientName = name; writeEEPROM(); for (int i=0; i < 5; i++) { fill_solid(leds, NUM_LEDS, CRGB::Black); FastLED.show(); delay(300); fill_solid(leds, NUM_LEDS, clientColor); FastLED.show(); delay(300); } Serial.print("Our name is "); Serial.println(clientName); } else { Serial.println("This is not us."); } } else if (payload[0] == 'G') { // game update event Serial.println("GAME UPDATE..."); int gameChoice = payload[1] - 48; if (gameChoice == ALL){ Serial.println("GAME SET TO ALL"); currentGame = ALL; } else if (gameChoice == AROUND){ Serial.println("GAME SET TO AROUND"); currentGame = AROUND; } else if (gameChoice == BLACKOUT){ Serial.println("GAME SET TO BLACKOUT"); currentGame = BLACKOUT; } else if (gameChoice == MOLE){ Serial.println("GAME SET TO WHACK-A-MOLE"); currentGame = MOLE; } else { Serial.println("UNKNOWN GAME"); } switchGame(); } else if (payload[0] == 'A') { //activate target event Serial.println("ACTIVATE TARGET EVENT"); char cPayload[length]; memcpy(cPayload, payload, length); String id; Serial.println(cPayload); int i = 1; while (cPayload[i] != 'I') { id += cPayload[i]; i++; } if (id.toInt() == ESP.getChipId()) { Serial.println("This is us."); gameEnabled = 1; fill_solid(leds, NUM_LEDS, clientColor); FastLED.show(); } } else if (payload[0] == 'D') { //deactivate target event Serial.println("DEACTIVATE TARGET EVENT"); char cPayload[length]; memcpy(cPayload, payload, length); String id; Serial.println(cPayload); int i = 1; while (cPayload[i] != 'I') { id += cPayload[i]; i++; } if (id.toInt() == ESP.getChipId()) { Serial.println("This is us."); gameEnabled = 0; fill_solid(leds, NUM_LEDS, CRGB::Black); FastLED.show(); } } else if (payload[0] == 'Y') { // activate all target event Serial.println("ACTIVATE ALL EVENT"); gameEnabled = 1; fill_solid(leds, NUM_LEDS, clientColor); FastLED.show(); } else if (payload[0] == 'Z') { // deactivate all target event Serial.println("DEACTIVATE ALL EVENT"); gameEnabled = 0; fill_solid(leds, NUM_LEDS, CRGB::Black); FastLED.show(); } break; case WStype_BIN: Serial.printf("[WSc] get binary length: %u\r\n", length); hexdump(payload, length); // send data to server // webSocket.sendBIN(payload, length); break; } } String buildRegister() { String output; output += "R"; output += ESP.getChipId(); output += "C"; output += clientColor; output += "N"; output += clientName; output += "^"; return output; } void setupWiFi() { WiFi.mode(WIFI_STA); Serial.print("Connecting to WIFI"); WiFi.begin(AP_NAME, AP_PASS); fill_solid(leds, NUM_LEDS, CRGB::Blue); FastLED.show(); while (WiFi.status() != WL_CONNECTED) { fill_solid(leds, NUM_LEDS, CRGB::Blue); FastLED.show(); Serial.print("."); delay(300); fill_solid(leds, NUM_LEDS, CRGB::Black); FastLED.show(); delay(300); } Serial.println("Connected!"); WiFi.printDiag(Serial); webSocket.begin("192.168.4.1", 81); webSocket.onEvent(webSocketEvent); } void setupEEPROM() { EEPROM.begin(512); if (EEPROM.read(0) == EEPROM_MAGIC_ID) { Serial.println("This is our EEPROM"); clientColor = (EEPROM.read(1))<<16&0xFF0000| (EEPROM.read(2))<<8&0x00FF00| (EEPROM.read(3))<<0&0x0000FF; Serial.print("Client color read from EEPROM as: "); Serial.println(clientColor); int i = 10; char buffer[40]; Serial.print("Reading name..."); while (EEPROM.read(i) != '@') { buffer[i] = EEPROM.read(i); clientName += buffer[i]; Serial.print(buffer[i]); i++; } Serial.println(" Done!"); Serial.print("Client name read from EEPROM as: "); Serial.println(clientName); } else { Serial.println("This is not our EEPROM, but we're taking it."); EEPROM.write(0, EEPROM_MAGIC_ID); EEPROM.write(1, 255); EEPROM.write(2, 255); EEPROM.write(3, 255); clientName = "FRESH"; for (int i=0; i> 16) & 0xFF)); Serial.println(((clientColor >> 8) & 0xFF)); Serial.println(((clientColor >> 0) & 0xFF)); EEPROM.write(1, ((clientColor >> 16) & 0xFF)); EEPROM.write(2, ((clientColor >> 8) & 0xFF)); EEPROM.write(3, ((clientColor >> 0) & 0xFF)); // write name Serial.print("Saving name. "); Serial.print(clientName); Serial.print(" length="); Serial.println(clientName.length()); for (int i=0; i NOISE) { if ((millis() - LOCKOUT) > lastUpdate) { fill_solid(leds, NUM_LEDS, CRGB::Black); FastLED.show(); Serial.println(adcRead); lastUpdate = millis(); String output = "H"; output += ESP.getChipId(); output += "F"; output += adcRead; output += "*"; webSocket.sendTXT(output); if (currentGame != ALL) { Serial.println("GOING OFFLINE DUE TO HIT AND GAME CHOICE != ALL"); gameEnabled = 0; fill_solid(leds, NUM_LEDS, CRGB::Black); } else if (currentGame == ALL) { Serial.println("STAYING ONLINE BECAUSE GAME IS ALL"); gameEnabled = 1; delay(300); fill_solid(leds, NUM_LEDS, clientColor); } FastLED.show(); } } } void setup() { Serial.begin(115200); pinMode(TARGETPIN, INPUT); FastLED.addLeds(leds, NUM_LEDS); // May need to change RGB order depending on which WS2812 you use //FastLED.addLeds(leds, NUM_LEDS); setupEEPROM(); setupWiFi(); lastUpdate = millis(); lastAnalogRead = millis(); } void loop() { webSocket.loop(); if ((millis() - ADC_READ_DELAY) > lastAnalogRead) { if (gameEnabled) { checkForImpact(); } lastAnalogRead = millis(); } }