Created
March 6, 2021 10:40
-
-
Save anthonyeden/a439bd3f14217b4a34cf1acfd274b6e2 to your computer and use it in GitHub Desktop.
Q-SYS Camera Tally - ESP32 M5StickC
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/***************** | |
ESP32 Tally Light for Q-SYS | |
Version 1.0 | |
A wireless (WiFi) tally light for Q-SYS, based on the M5StickC ESP32 development board and the Arduino IDE. | |
Based on: https://github.com/oneguyoneblog/tally-light-esp32-for-blackmagic-atem-switcher/blob/master/tally-light-esp32-for-blackmagic-atem-switcher.ino | |
******************/ | |
#include <M5StickC.h> | |
#include <WiFi.h> | |
#include <esp_wifi.h> | |
WiFiClient client; | |
IPAddress qsysIp(10, 1, 1, 9); // IP address of the Q-SYS Core | |
int qsysPortNumber = 10001; // Port number for this TCP server on Q-SYS (one TCP server per tally) | |
const char* ssid = "WIFI NETWORK NAME"; | |
const char* password = "1234567890"; | |
int ledPin = 10; | |
String TCPReceived = ""; | |
// Set your new MAC Address | |
uint8_t newMACAddress[] = {0x32, 0xAE, 0xA4, 0x07, 0x0D, 0x66}; | |
void setup() { | |
Serial.begin(9600); | |
// initialize the M5StickC object | |
M5.begin(); | |
Serial.println("Beginning session"); | |
// Blank the screen | |
String resetString = "X"; | |
drawLabel(0xF800, 0, LOW, resetString); | |
// Start the Ethernet, Serial (debugging) and UDP: | |
WiFi.begin(ssid, password); | |
Serial.print("ESP Board MAC Address: "); | |
Serial.println(WiFi.macAddress()); | |
while (WiFi.status() != WL_CONNECTED) { | |
delay(500); | |
Serial.println("Connecting to WiFi.."); | |
} | |
Serial.println("Connected to the WiFi network"); | |
pinMode(ledPin, OUTPUT); // LED: 1 is on Program (Tally) | |
digitalWrite(ledPin, HIGH); // off | |
// Initialize a connection to the Q-SYS: | |
connect_qsys(); | |
} | |
void connect_qsys() { | |
if (client.connect(qsysIp, qsysPortNumber)) { | |
Serial.println("connected"); | |
} else { | |
Serial.println("connection failed"); | |
delay(1000); | |
connect_qsys(); | |
} | |
} | |
void loop() { | |
if (!client.connected()) { | |
Serial.println("disconnecting."); | |
client.stop(); | |
connect_qsys(); | |
} | |
if (client.available() > 0) { | |
char thisChar = client.read(); | |
TCPReceived = String(TCPReceived) + String(thisChar); | |
if (thisChar == '\n') { | |
// Parse commands in TCPReceived, then reset it | |
String screenColor = getValue(TCPReceived, ';', 0); | |
unsigned long int screenColor2 = atol(screenColor.c_str()); | |
String labelColor = getValue(TCPReceived, ';', 1); | |
unsigned long int labelColor2 = atol(labelColor.c_str()); | |
String ledValue = getValue(TCPReceived, ';', 2); | |
bool ledValueBool = HIGH; | |
if (ledValue == "LOW") { | |
ledValueBool = LOW; | |
} | |
String textDisplay = getValue(TCPReceived, ';', 3); | |
// Update the display | |
drawLabel(screenColor2, labelColor2, ledValueBool, textDisplay); | |
// Reset the buffer | |
Serial.println(TCPReceived); | |
TCPReceived = ""; | |
} | |
} | |
} | |
void drawLabel(unsigned long int screenColor, unsigned long int labelColor, bool ledValue, String textDisplay) { | |
digitalWrite(ledPin, ledValue); | |
M5.Lcd.fillScreen(screenColor); | |
M5.Lcd.setTextColor(labelColor, screenColor); | |
M5.Lcd.setTextSize(6); | |
M5.Lcd.drawString(textDisplay, 15, 40); | |
} | |
String getValue(String data, char separator, int index) { | |
// https://stackoverflow.com/questions/9072320/split-string-into-string-array | |
int found = 0; | |
int strIndex[] = {0, -1}; | |
int maxIndex = data.length() - 1; | |
for (int i = 0; i <= maxIndex && found <= index; i++) { | |
if (data.charAt(i) == separator || i == maxIndex) { | |
found++; | |
strIndex[0] = strIndex[1] + 1; | |
strIndex[1] = (i == maxIndex) ? i + 1 : i; | |
} | |
} | |
return found > index ? data.substring(strIndex[0], strIndex[1]) : ""; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
server = TcpSocketServer.New() | |
-- Specify the input number on the ATEM | |
thisInputNumber = 1 | |
-- Stores the state of the ATEM | |
currentPgm = 0 | |
currentPvw = 0 | |
server.EventHandler = function(SocketInstance) | |
-- Setup a connection handler. One handler per connection | |
SocketInstance.ReadTimeout = 0 | |
print( "Got connect", SocketInstance ) | |
SocketInstance.EventHandler = SocketHandler | |
timer_func(SocketInstance) | |
end | |
function SocketHandler(NewSocketInstance, event) | |
-- Get new TCP data from any connected client | |
print( "TCP Socket Event: "..event ) | |
end | |
-- On script startup, begin listing on TCP port 20001 | |
server:Listen(2000 .. thisInputNumber) | |
function timer_func(SocketInstance) | |
Timer.CallAfter(function() | |
timer_func(SocketInstance) | |
end, 0.5) | |
changed = false | |
for i=1,8 do | |
if NamedControl.GetValue("ATEMControlStreaming:ScriptableControlsME1Program" .. i) == 1.0 and currentPgm ~= i then | |
currentPgm = i | |
changed = true | |
end | |
if NamedControl.GetValue("ATEMControlStreaming:ScriptableControlsME1Preview" .. i) == 1.0 and currentPvw ~= i then | |
currentPvw = i | |
changed = true | |
end | |
end | |
-- OUTPUT FORMAT: BG_COL;TXT_COL;LOW/HIGH;TEXT | |
if changed == true then | |
if currentPgm == thisInputNumber then | |
SocketInstance:Write("1700000;0;LOW;" .. currentPgm .. "\n") | |
elseif currentPvw == thisInputNumber then | |
SocketInstance:Write("600000;0;HIGH;" .. currentPgm .. "\n") | |
else | |
SocketInstance:Write("0;600000;HIGH;" .. currentPgm .. "\n") | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment