Last active
January 23, 2022 15:33
-
-
Save mpflaga/b93d8375a10af06143b2 to your computer and use it in GitHub Desktop.
Sketch to daisy chain Arduino Mega's from a PC running Vixen, as to get infinite Cue's.
This file contains hidden or 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
/* | |
This sketch is used with Vixen Sequence to allow Arduino's to be daisy chained. | |
see for details. | |
http://stackoverflow.com/questions/27172147/arduino-serial-communcation-with-vixen | |
*/ | |
#define FIRST_IN_CHAIN 1 // set this to 1 for the first in Chain | |
#define SIZE_OF_ARRAY(X) (sizeof(X)/sizeof(X[0])) //total length divided by length of one element | |
// As specified in Vixen's General Serial Port Setup "Send a Text Footer" | |
#define VIXEN_END_OF_TEXT 'E' | |
#if (FIRST_IN_CHAIN == 1) | |
#define SERIALIN Serial | |
#else | |
#define SERIALIN Serial2 | |
#endif | |
// General GPIO used to output Cues | |
uint8_t pins[] = {3,4,5,6,7,8,9,10,11,12,13,\ | |
// not used SerialX ports | |
// 14,15, \ // TXD3/RXD3 | |
// 16,17, \ // TXD2/RXD2 | |
// 18,19, \ // TXD1/RXD1 | |
// 20,21, \ // SDA/SCL | |
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}; | |
void setup() { | |
SERIALIN.begin(9600); | |
Serial3.begin(9600); | |
// initialize cue pins OFF and Output | |
for (uint8_t pin = 0; pin < SIZE_OF_ARRAY(pins); pin++) { | |
digitalWrite(pins[pin], LOW); | |
pinMode(pins[pin], OUTPUT); | |
} | |
} | |
void loop() | |
{ | |
// get first 43 cues for this Arduino | |
for (uint8_t pin = 0; pin < SIZE_OF_ARRAY(pins); pin++) { | |
while(!SERIALIN.available()); // wait for some data. | |
char c = SERIALIN.read(); | |
if(c == VIXEN_END_OF_TEXT) { | |
return; | |
} | |
else if(c > 0x00) { | |
digitalWrite(pins[pin], HIGH); | |
} | |
else { | |
digitalWrite(pins[pin], LOW); | |
} | |
} | |
// read from port 0, send to port 1: | |
while(1) { | |
while(!SERIALIN.available()) ; // wait for next data. | |
char c = SERIALIN.read(); | |
if(c == VIXEN_END_OF_TEXT) { | |
// when Carriage Return is received Exit while and wait for new frame | |
break; | |
} | |
else { | |
// echo byte on to the next stage | |
Serial3.write(c); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
The typical example that appears to be proliferated for Arduino's receiving from Vixen. Is scary in that it does not frame the Start or End of the stream of cues. Rather it requires the stream to be and stay synchronized, being dependent upon the length. This will work until ONE byte is lost. Then everything will be out of sync until reset and restarted. Something you will not want to do with multiple Arduino's.
Now this is not perfect and since I don't have a Vixen and such set up it has not been proven. However, it does compile and appears it should work fine.
In general it appears that Vixen sends out the stream of bytes of Cue's terminating the frame with a Carriage Return or possibly Line Feed. So the above sketch listens for the first 43 cues and applies them to the local pins. Then echos the remainder out Serial3 to the next Arduino, until a CR or LF is received denoting the end of Frame. At which point it starts over. Note the cue's locally applied are not echo'ed, this means the next Arduino will again act on the first 43 cues and echo the remained until the chain is exhausted. It is required that the last unit get all 43. So if the total count is short it then that last unit will not properly continue. (Something for the future. Or it may be best to pad a few extra on the end of the Vixen's output.)
Note the use of
Which is effectively "wait while there is no data to be read" or wait until there is something. These are Blocking (meaning the code is stuck) until something is received. Whereas it is expected that Vixen will periodically be sending the stream of cues. And even if ONE CR/LF is missed the next frame will have it, so that the code will autonomously resynchronize.
Also worth noting the pins to cue definition is more flexible. If you want to possible use 47 cues, un-comment:
// 18,19, \ // TXD1/RXD1
// 20,21, \ // SDA/SCL
the code will automatically resize. Or comment out other pins if used for other purposes.
To summarize the first unit is compiled with FIRST_IN_CHAIN defined as 1. This causes the lead ArduinoMega to receive the data from Serial port attached to the PC running Vixen. The remaining Mega's are compiled with FIRST_IN_CHAIN defined as 0. Where the Serial3 of the preceding unit is connected to the next units Serial2. It is possible to drive into Serial. Where it is simpler to reserve Serial for debugging and such.
And don't forget to connect a common ground along with RxD and TxD.