These are the details of the switch box I constructed for my DCS World project and the Arduino code used. The switches themselves are simple push buttons and SPDT type toggle switches. The box itself is a small storage container from Home Depot.
As you can see, I followed a simple color code within the box to keep things orderly (wires were ordered by wire color and then further separated by shrink-tube color). I used a CAT6 cable with re-terminated ends to carry the multiplexer address signals to the box/ICs as well as carry the input signals from the switches back to the Arduino. The 8 lines within the CAT6 cable allow for 2 lines of +/- power, 3 address lines (common addressing is used with all multiplexers), and 3 remaining lines for reading the output pins of 3 multiplexers. This allows for quick reading of up to 24 switch states with no significant delay. Fancier data bus architectures could allow for time-synchronized sharing of the lines, but I don’t have time to implement that (see what I did there?).
Here is the simple Arduino code I wrote to check the multiplexer+switches functionality:
int ad0pin = 11;
int ad1pin = 12;
int ad2pin = 13;
int inPin1 = 2;
int inPin2 = 3;
int j = 7;
int switches[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
int swMem[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
int LHs0[] = {LOW, HIGH, LOW, HIGH, LOW, HIGH, LOW, HIGH};
int LHs1[] = {LOW, LOW, HIGH, HIGH, LOW, LOW, HIGH, HIGH};
int LHs2[] = {LOW, LOW, LOW, LOW, HIGH,HIGH, HIGH, HIGH};
void setup() {
// put your setup code here, to run once:
pinMode(ad0pin, OUTPUT);
pinMode(ad1pin, OUTPUT);
pinMode(ad2pin, OUTPUT);
pinMode(inPin1, INPUT_PULLUP);
pinMode(inPin2, INPUT_PULLUP);
Serial.begin(9600);
while (!Serial){
; // wait for the serial port to connect
}
Serial.println("4051 Multiplexer Sketch vB.8");
}
void loop() {
// put your main code here, to run repeatedly:
for (byte i=0; i < 8; ++i)
{
digitalWrite(ad0pin, LHs0[i]);
digitalWrite(ad1pin, LHs1[i]);
digitalWrite(ad2pin, LHs2[i]);
delay(20);
switches[i] = digitalRead(inPin1);
switches[i+8] = digitalRead(inPin2);
delay(20);
}
for(int i = 0; i < 16; i++)
{
if(swMem[i] != switches[i]) {
String SwStat = "switch ";
SwStat = SwStat + (i+1) + " = " + switches[i];
Serial.println(SwStat);
}
swMem[i] = switches[i];
}
//delay(50);
}
Here is the more involved code for sending the multiplexer data out over Ethernet. There is reference to something I call ‘XmitPin’ because I wanted to create feedback from the DCS simulator back to an LED via the same routing; it is not used on the current version of the switch box.
#include <Ethernet.h>
#include <SPI.h>
#include <EthernetUdp.h>
// ad#pin refers to address pins used to set the 8 channel multiplexers
// inPin refers to the read pins from the individual multiplexers
int ad0pin = 11;
int ad1pin = 12;
int ad2pin = 13;
int inPin1 = 2;
int inPin2 = 3;
int XmitPin = 6;
// This sets the current state of the variables for the pins
int switches[] = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};
int swMem[] = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};
// These arrays dictate the order to set each of the address pins of the multiplexers
int LHs0[] = {LOW, HIGH, LOW, HIGH, LOW, HIGH, LOW, HIGH};
int LHs1[] = {LOW, LOW, HIGH, HIGH, LOW, LOW, HIGH, HIGH};
int LHs2[] = {LOW, LOW,LOW,LOW,HIGH,HIGH,HIGH,HIGH};
char SwStat [5];
unsigned long time;
unsigned long oldtime;
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress MyIPAddress(192,168,1,167); // The Arduino
unsigned int localPort = 8090;
IPAddress ServerIP(192,168,1,121); // The computer
unsigned int ServerPort(9000);
EthernetUDP Udp;
char packetBuffer[UDP_TX_PACKET_MAX_SIZE];
char *ptr = NULL;
char *parm = NULL;
char *val = NULL;
int counter = 0;
void setup()
{
pinMode(ad0pin, OUTPUT);
pinMode(ad1pin, OUTPUT);
pinMode(ad2pin, OUTPUT);
pinMode(XmitPin, OUTPUT);
pinMode(inPin1, INPUT_PULLUP);
pinMode(inPin2, INPUT_PULLUP);
Serial.begin(9600);
while (!Serial){
; // wait for the serial port to connect
time = millis();
oldtime = millis();
}
Ethernet.begin(mac, localPort);
Serial.println("Sketch v3.0");
Serial.print("Local IP: ");
Serial.println(Ethernet.localIP());
Serial.println("Opening port...");
Udp.begin(localPort);
Udp.beginPacket(ServerIP,ServerPort);
Udp.write("Arduino Online");
Udp.endPacket();
}
void loop()
{
int packetSize = Udp.parsePacket();
if(packetSize)
{
Serial.print("Received packet of size ");
Serial.println(packetSize);
Udp.read(packetBuffer,packetSize); // UDP_TX_PACKET_MAX_SIZE);
Serial.println("Contents:");
Serial.println(packetBuffer);
byte index = 0;
parm = strtok(packetBuffer,":");
val = strtok(NULL,":");
Serial.print("Contents: ");
Serial.println(parm);
Serial.println(val);
if(strcmp(parm,"Xmit")==0)
Serial.println("Received Xmit");
{
if(strcmp(val,"true")==0)
{
digitalWrite(XmitPin, 1);
Serial.println("Radar Xmit");
}
else if (strcmp(val,"false")==0)
{
digitalWrite(XmitPin, 0);
}
}
}
delay(5);
for (byte i=0; i < 8; ++i)
{
digitalWrite(ad0pin, LHs0[i]);
digitalWrite(ad1pin, LHs1[i]);
digitalWrite(ad2pin, LHs2[i]);
delay(5);
switches[i] = digitalRead(inPin1);
switches[i+8] = digitalRead(inPin2);
delay(5);
}
String SwStat = String("Sw999,0/");
char SwStatNew[11];
Udp.beginPacket(ServerIP,ServerPort);
for(int i = 0; i < 8; i++)
{
if(swMem[i] != switches[i]) {
sprintf(SwStatNew,"Sw%03d,%1d/",i+1,switches[i]);
SwStat = String(SwStatNew);
Udp.print(SwStat);
Udp.endPacket();
swMem[i] = switches[i];
}
}
//time = millis();
//float rate = 1000/(time-oldtime);
//Serial.print("update rate = ");
//Serial.println(rate);
//oldtime = time;
for(int i=0;i<UDP_TX_PACKET_MAX_SIZE;i++) packetBuffer[i] = 0;
}