// Include Section #include "esp_dmx.h" #include "rdm/controller.h" #include "rdm/responder.h" #include "UUID.h" #include "EEPROM.h" #define INTERRUPT_PIN 0 #include #include #include #include bool debugMode = true; int bleCharCount; const int channelPerLamp = 4; const int expectedLampCount = 25; const int dmxPacketSize = channelPerLamp * expectedLampCount + 1; // struct Button { const uint8_t PIN; uint32_t numberKeyPresses; bool pressed; }; uint8_t dmxData[DMX_PACKET_SIZE] = {0}; BLEServer* pServer = NULL; bool deviceConnected = false; bool oldDeviceConnected = false; uint16_t SERVICE_UUID = 20241115; const int panelAmount = 25; BLECharacteristic* pCharacteristics[panelAmount]; char* CHARACTERISTIC_UUIDS[panelAmount]; class MyServerCallbacks: public BLEServerCallbacks { void onConnect(BLEServer* pServer) { deviceConnected = true; }; void onDisconnect(BLEServer* pServer) { deviceConnected = false; } }; // Defining BOOT button on ESP32 as our built-in button. Button button1 = {INTERRUPT_PIN, 0, false}; int mode = 0; const int modeAmount = 16; uint8_t brightnessMax = 20; uint8_t universalBrightness = 10; uint8_t dataSeq[modeAmount][DMX_PACKET_SIZE] = { { 0, 0,0,universalBrightness,0, 0,0,universalBrightness,0, 0,0,universalBrightness,0, 0,0,universalBrightness,0, 0,0,universalBrightness,0, 0,0,universalBrightness,0, 0,0,universalBrightness,0, 0,0,universalBrightness,0, 0,0,universalBrightness,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0 }, { 0, 0,universalBrightness,0,0, 0,universalBrightness,0,0, 0,universalBrightness,0,0, 0,universalBrightness,0,0, 0,universalBrightness,0,0, 0,universalBrightness,0,0, 0,universalBrightness,0,0, 0,universalBrightness,0,0, 0,universalBrightness,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0 }, { 0, universalBrightness,0,0,0, universalBrightness,0,0,0, universalBrightness,0,0,0, universalBrightness,0,0,0, universalBrightness,0,0,0, universalBrightness,0,0,0, universalBrightness,0,0,0, universalBrightness,0,0,0, universalBrightness,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0 }, { 0, universalBrightness,0,0,0, // Orange 0,universalBrightness,0,0, // White 0,universalBrightness,0,0, // White 0,0,universalBrightness,0, // Blue 0,0,universalBrightness,0, 0,0,universalBrightness,0, 0,0,universalBrightness,0, 0,0,universalBrightness,0, 0,universalBrightness,0,0, //End Inner Round //Start Outer Round 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0 }, { 0, //Start Inner Round 0,0,universalBrightness,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, //End Inner Round //Start Outer Round universalBrightness,0,0,0, universalBrightness,0,0,0, universalBrightness,0,0,0, universalBrightness,0,0,0, universalBrightness,0,0,0, universalBrightness,0,0,0, universalBrightness,0,0,0, universalBrightness,0,0,0, universalBrightness,0,0,0, universalBrightness,0,0,0, universalBrightness,0,0,0, universalBrightness,0,0,0, universalBrightness,0,0,0, universalBrightness,0,0,0, universalBrightness,0,0,0, universalBrightness,0,0,0 } } ; void IRAM_ATTR isr() { button1.pressed = true; }; void ledBlink(int interval, int pinNumber) { digitalWrite( pinNumber, !digitalRead(pinNumber) ); delay(interval); }; void dmxSetup() { const dmx_port_t dmx_num = DMX_NUM_1; Serial.printf("\nSetting up DMX Port %d", dmx_num); // First, use the default DMX configuration... dmx_config_t config = DMX_CONFIG_DEFAULT; // Declare Personality RGBW const int personality_count = 1; Serial.print("\nDefining DMX Personality... "); dmx_personality_t personalities[] = { {4, "RGBW"} }; Serial.print("Done"); Serial.print("\nInstalling DMX Driver... "); // ...install the DMX driver... dmx_driver_install(dmx_num, &config, personalities, personality_count); Serial.print("Done"); // ...and then set the communication pins! const int tx_pin = 23; const int rx_pin = 22; const int rts_pin = 21; Serial.printf("\nSetting up pin %d as Transmit Pin, pin %d as Receive Pin and pin %d as RTS Pin... ", tx_pin, rx_pin, rts_pin); dmx_set_pin(dmx_num, tx_pin, rx_pin, rts_pin); Serial.print("Done\n"); } void serialRead(){ String incomingByte; if (Serial.available() > 0) { // read the incoming byte: incomingByte = Serial.readStringUntil('\r\n'); Serial.print("\nI received: "); Serial.print(incomingByte); mode = incomingByte.toInt(); } } void setup() { Serial.begin(115200); delay(2000); Serial.print("\nIf you receive this message, ESP32 module has finished setting up Serial Interface for communication."); pinMode(INTERRUPT_PIN, INPUT_PULLUP); attachInterrupt(digitalPinToInterrupt(INTERRUPT_PIN), isr, RISING); //Begin of the DMX Setup const dmx_port_t dmx_num = DMX_NUM_1; dmxSetup(); Serial.println("Welcome to Pupilometer LED Billboard!"); const int array_size = 25; rdm_uid_t uids[array_size]; // This function blocks and may take some time to complete! Serial.printf("Attempting to Discover the Existing DMX Network... "); int num_uids = rdm_discover_devices_simple(DMX_NUM_1, uids, array_size); Serial.printf("Done!\n"); Serial.printf("Discovery found %i UIDs as following:\n", num_uids); for (int i = 0; i < num_uids; i++){ printf(UIDSTR "\n", UID2STR(uids[i])); }; // Create the BLE Device BLEDevice::init("Pupilometer LED Billboard"); // Create the BLE Server pServer = BLEDevice::createServer(); pServer->setCallbacks(new MyServerCallbacks()); // Create the BLE Service BLEService *pService = pServer->createService(SERVICE_UUID,52); const bool debugMode = false; // Serial.printf(debugMode); // Create a BLE Characteristic Serial.printf("\nCalculating BLE Charateristic Count"); bleCharCount = (panelAmount * debugMode) + !debugMode; Serial.printf("\nCalculating BLE MTU ..."); uint16_t bleMTU = ((panelAmount * 3) / bleCharCount) + 3; Serial.printf("\nSetting BLE MTU to %i bytes... ", bleMTU); BLEDevice::setMTU(bleMTU + 3); Serial.printf("Done!\n"); for (uint32_t i = 0; i < bleCharCount; i++){ //UUID uuid; //uuid.seed(i+1); //uuid.generate(); //Serial.printf("Creating BLE Characteristic with UUID %s ...", BLEUUID(i+1)); pCharacteristics[i] = pService->createCharacteristic( i+1, // BLEUUID(uuid.toCharArray()), BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_WRITE | BLECharacteristic::PROPERTY_NOTIFY | BLECharacteristic::PROPERTY_INDICATE ); Serial.printf("Created BLE Characteristic with UUID %s ...", pCharacteristics[i]->getUUID().toString().c_str()); // pCharacteristics[i]->addDescriptor(new BLE2902()); // Serial.printf("Done\n"); }; // Start the service pService->start(); // Start advertising BLEAdvertising *pAdvertising = BLEDevice::getAdvertising(); pAdvertising->addServiceUUID(SERVICE_UUID); pAdvertising->setScanResponse(false); pAdvertising->setMinPreferred(0x0); // set value to 0x00 to not advertise this parameter BLEDevice::startAdvertising(); } void loop() { // Save Old Mode int modeOld = mode; int msgSize; uint8_t* btMessage[bleCharCount]; // uint8_t dmxData[DMX_PACKET_SIZE] = {0}; // notify changed value if (deviceConnected) { } // disconnecting if (!deviceConnected && oldDeviceConnected) { delay(500); // give the bluetooth stack the chance to get things ready pServer->startAdvertising(); // restart advertising Serial.println("Start advertising"); oldDeviceConnected = deviceConnected; } // connecting if (deviceConnected && !oldDeviceConnected) { // do stuff here on connecting oldDeviceConnected = deviceConnected; } // Serial.printf("\nConstructing Payload using "); // Serial.printf("Bluetooth Data ..."); if (button1.pressed){ if (mode < modeAmount - 1){mode++;} else {mode = 0;}; // Increment the value of each slot, excluding the start code. button1.pressed = false; // Reset button status to FALSE }; serialRead(); if (modeOld != mode){ Serial.printf("\nChanging Lighting Preset to Preset %d", mode); uint8_t lampData[DMX_PACKET_SIZE / 4 * 3]; Serial.printf("\nDetected preset %i size: %i", mode, sizeof(dataSeq[mode])); for (int i = 0; i < sizeof(dataSeq[mode]); i++){ dmxData[i] = dataSeq[mode][i]; int sublampIndex = i % 4; //Serial.printf("[%i]", sublampIndex, j); if (sublampIndex > 0) { int j = (i / 4) * 3 + sublampIndex - 1; Serial.printf("[%i](%i)", j, sublampIndex); lampData[j] = dataSeq[mode][i]; } }; pCharacteristics[0]->setValue(lampData, expectedLampCount * 3); } Serial.printf("\nConstructing DMX Payload with size "); for (int i = 0; i < bleCharCount; i++){ btMessage[i] = pCharacteristics[i]->getData(); msgSize = pCharacteristics[i]->getLength(); Serial.printf("%i bytes ", msgSize); for (int j = 0; j < msgSize; j++){ int packet = btMessage[i][j]; int lampSum = i*3 + j; int dmxAddress = (lampSum / 3) * 4 + lampSum % 3 + 1; dmxData[dmxAddress] = packet; // Serial.printf("[[%i,%i] %i - %i] ",i , j, dmxAddress, packet); }; }; Serial.printf("\n"); // Serial.printf(" Done"); // Wait until the packet is finished being sent before proceeding. dmx_wait_sent(DMX_NUM_1, DMX_TIMEOUT_TICK); // Now write the packet synchronously! dmx_write(DMX_NUM_1, dmxData, DMX_PACKET_SIZE); dmx_send(DMX_NUM_1); }