Arduino e1.31 to Drive Relays

brainless

New elf
Joined
Jan 8, 2015
Messages
10
Hi All,

Im chasing assistance to program an ethermega+w5100 to drive Relays via the Digital Pins
Does anyone have code to do this, i have been able to use keithsw1111's code to drive Pixels which is great but unable to get it to trigger the relays
 

AAH

I love blinky lights :)
Community project designer
Joined
Dec 27, 2010
Messages
3,389
Location
Eaglehawk
Are you attempting to drive the relays correctly? The Arduino probably doesn't have the drive current (or protection) to drive a relay directly. Can you pop up details of your Arduino to relay interface.
 

brainless

New elf
Joined
Jan 8, 2015
Messages
10
My code does do relays. There is a #define there for that
Thanks keith im probably just not using it properly, what changes are needed to the code to use relays and which pins are they triggered from


The relays i use are prebuilt arduino shields that trigger on 5v, i have used them in previous years with serial code on the arduino for my christmas tree but with a move to starting on the house im looking to use e1.31
 

Attachments

AAH

I love blinky lights :)
Community project designer
Joined
Dec 27, 2010
Messages
3,389
Location
Eaglehawk
Are you supplying the boards with both 0V and 5V along with the Arduino outputs?
 

keithsw1111

Senior elf
Joined
Oct 11, 2012
Messages
589
Location
Kellyville, NSW
I thin you just uncomment the relay universe in global.h

There is a header file which lists the pins that are activated. If I remember rightly there are about 24 of them.
 

brainless

New elf
Joined
Jan 8, 2015
Messages
10
Just an update, I was not able to successfully drive the relays with the code but i found another code which is also able to be used with my uno arduinos and should be more than sufficient for the relays per Arduino

If anyone wants to use it i have put it below, ensure that the relays are wired on the NC side

All thats needed to be modified in the code is the IP Address, MAC Address (if using more than one) and Pinout that you want to use

This has been tested on

Ethermega
Mega+w5100
Uno+5100
EtherTen

Code:
/*
Original code created January 4th, 2014 by Claude Heintz http://lx.claudeheintzdesign.com/lxarduino_sketches.html
modified by: Jared Alexander

This code is in the public domain.
sACN E 1.31 is a public standard published by the PLASA technical standards program
http://tsp.plasa.org/tsp/documents/published_docs.php

Requires Arduino Ethernet Shield. Modifed to use the lastest version of Ethernet library included in Arduino 1.6.1. No need to install other libraries. 
Receives E1.31 data (SACN) and ArtNet data for control of relays. This sketch is designed for use with SainSmart Relay boards. 
You can only send the Arduino one protocol (E1.31 or ArtNet) at a time. 
This sketch also includes a power on self test function to make sure everything is hooked up properly.
*/

#include <SPI.h>    //Standard Library     
#include <Ethernet.h> //Standard Library
#include <EthernetUdp.h> //Standard Library


/*  set the desired subnet and universe (first universe is 0)
    sACN starts with universe 1 so subtract 1 from sACN universe
    to get DMX_UNIVERSE.                                           */
#define ARTNET_SUBNET 0 //defualt subnet is 0. Should not need to be changed. 
#define ARTNET_UNIVERSE 0 //first universe being used
#define E131_SUBNET 0 //defualt subnet is 0. Should not need to be changed. 
#define ETHERNET_BUFFER_MAX 640
#define ARTNET_ARTDMX 0x5000
#define ARTNET_ARTPOLL 0x2000
#define ARTNET_PORT 0x1936 //standard port
#define ARTNET_START_ADDRESS 18 //Byte 18 in the packet contains channel 1 values. 
#define E131_PORT 5568 //standard port 
#define E131_START_ADDRESS 126 //Byte 126 in the packet contains channel 1 values. Offset is set to one prior. 
#define STATUS_LED 13 //shows us when we are receiving data
#define SDCARD_CONTROL 4 //set pin 4 to high to disable SD card interface on WiFi shield 
#define NUM_RELAYS 8 //total number of relays used 

int channel; //channel increment 

//Relay Pins array
int Relay[] = {2, 3, 5, 6, 7, 8, 9, 10,};

//Timer Setup
volatile byte currentcounter = 0; //counter for data reception
byte previouscounter = 0; //counter for data reception 
unsigned long currentDelay = 0; //current time value for ArtNet and E1.31 reception

//Ethernet Configuration
byte mac[] = {0x00, 0xDD, 0xEE, 0x01, 0x10, 0x97};
IPAddress ip(192, 168, 1, 213);  //IP address of ethernet shield

// buffer to hold E1.31 and Artnet data
unsigned char packetBuffer[ETHERNET_BUFFER_MAX];

// An EthernetUDP instance to let us send and receive packets over UDP
// aUDP creates a socket for an Art-Net port
// suUDP creates a socket for sACN that is unicast to the ip address
EthernetUDP aUDP;
EthernetUDP suUDP;

void setup() 
{
  pinMode(STATUS_LED, OUTPUT); //Initialize status LED
  pinMode(SDCARD_CONTROL, OUTPUT); //Initialize Pin 4
  digitalWrite(SDCARD_CONTROL, HIGH); //Set pin 4 to high since we are not using the SD Card interface
  for(int a = 0; a < NUM_RELAYS; a++) //loop to initialize relay control pins 
  {
   pinMode(Relay[a], OUTPUT); //initialize relay output pins
   digitalWrite(Relay[a], LOW); //set pins to high for off
  }
  Ethernet.begin(mac,ip);  //Initialize Ethernet shield 
  aUDP.begin(ARTNET_PORT); //Open Artnet Port
  suUDP.begin(E131_PORT); //Open E1.31 Port
  Serial.begin(9600); //Serial for debugging 
  POST(); //Run Power On Self Test Function
  Serial.println("Setup Complete"); //print complete 
}

/* artDMXReceived checks the universe and subnet then
   outputs the data to the relays */

void artDMXReceived(unsigned char* pbuff) 
{
  if ( (pbuff[14] & 0xF) == ARTNET_UNIVERSE ) 
  {
    if ( (pbuff[14] >> 8) == ARTNET_SUBNET ) 
    {
      channel = 0; //reset channel offset to 0 each time through loop
      //loop turns relay on/off based on channel value starting at Artnet start address
      for(int b = 0; b < NUM_RELAYS; b++) 
      {
       if(pbuff[ARTNET_START_ADDRESS + channel] > 127) //if channel value is greater then 127
      {
       digitalWrite(Relay[b], HIGH); //turn relay on 
      } 
      else
      {
       digitalWrite(Relay[b], LOW); //else turn it off 
      }
      channel++; //increase channel offset by 1 each time through for loop
      }
    }
  }
} //end artDMXReceived 

/*  artNetOpCode checks to see that the packet is actually Art-Net
    and returns the opcode telling what kind of Art-Net message it is.  */

int artNetOpCode(unsigned char* pbuff) 
{
  String test = String((char*)pbuff);
  if ( test.equals("Art-Net") ) 
  {
    if ( pbuff[11] >= 14 ) 
    {            //protocol version [10] hi byte [11] lo byte
      return pbuff[9] *256 + pbuff[8];  //opcode lo byte first
    }
  }
 
  return 0;
}

/* sacnDMXReceived checks the universe and subnet then
   outputs the data to relays  */

void sacnDMXReceived(unsigned char* pbuff, int count) 
{
    if ( pbuff[113] == E131_SUBNET ) 
  { 
      int addressOffset = 125; //first 125 bytes of packet are header information
      if ( pbuff[addressOffset] == 0 ) //start code must be 0
      { 
       channel = 0; //reset channel offset to 0 each time through loop
       //loop turns relay on/off based on channel value starting at E1.31 start address
      for(int c = 0; c < NUM_RELAYS; c++)
      {
       if(pbuff[E131_START_ADDRESS + channel] > 127) //if channel value is greater then 127
      {
       digitalWrite(Relay[c], LOW); //turn relay on
      } 
      else
      {
       digitalWrite(Relay[c], HIGH); //turn relay off 
      }
      channel++; //increment channel offset by 1
      }
      }
      } 
    } //end sacnDMXReceived 
   
 
 
//checks to see if packet is E1.31 data
int checkACNHeaders(unsigned char* messagein, int messagelength) 
{
  if ( messagein[1] == 0x10 && messagein[4] == 0x41 && messagein[12] == 0x37) 
  { 
      int addresscount = messagein[123] * 256 + messagein[124]; // number of values plus start code
      return addresscount -1; //Return how many values are in the packet.
    }
  return 0;
}

/************************************************************************
  The main loop checks for and reads packets from the two UDP ethernet
  socket connections.  When a packet is recieved, it is checked to see if
  it is valid and then one of the DMXReceived functions is called, sending
  the DMX values to the output. There also is a timer to run a standby 
  program if no data is received for 30 seconds. 
*************************************************************************/

void loop() 
{
  if(currentcounter != previouscounter) //has the value changed?
  {
    currentDelay = millis(); //store the time since the value has increased 
    previouscounter = currentcounter; //set the previous value equal to the current value
  }
 
  if(millis() - currentDelay > 30000) //is the time since the value changed greater than 30 seconds?
  { 
   digitalWrite(STATUS_LED, LOW); //turn LED off. Not receiving E1.31 or ArtNet. 
  }
 
  // first check to see if a packet is available on the Art-Net port
  int packetSize = aUDP.parsePacket();
  if( packetSize )
  {
    aUDP.read(packetBuffer, ETHERNET_BUFFER_MAX);
    /* after reading the packet into the buffer, check to make sure
       that it is an Art-Net packet and retrieve the opcode that
       tells what kind of message it is                         */
    int opcode = artNetOpCode(packetBuffer);
    if ( opcode == ARTNET_ARTDMX ) 
    {
      Serial.println("ArtNet Packet Received");
      artDMXReceived(packetBuffer);
      currentcounter++;  //increase counter by 1 each time through 
      digitalWrite(STATUS_LED, HIGH); //turn status LED on
    } 
  } 
    else 
    {
      /* then, if still no packet, check to see if a packet
         is available on the sACN unicastcast port         */
       packetSize = suUDP.parsePacket();
    if( packetSize ) 
    {
      suUDP.read(packetBuffer, ETHERNET_BUFFER_MAX);
      /* after reading the packet into the buffer, check to make sure
       that it is a valid sACN packet.*/
      int count = checkACNHeaders(packetBuffer, packetSize);
      if ( count ) 
      {
        Serial.println("E131 Packet Received");
        sacnDMXReceived(packetBuffer, count);
        currentcounter++;  //increase counter by 1 each time through 
      digitalWrite(STATUS_LED, HIGH); //turn status LED on
      }
    }
     
    }
 
} //End loop

//Power on self test function to make sure everything is connected properly. 
void POST()
{
  digitalWrite(Relay[0], LOW);
  delay(1000);
  digitalWrite(Relay[0], HIGH);
  digitalWrite(Relay[1], LOW);
  delay(1000);
  digitalWrite(Relay[1], HIGH);
  digitalWrite(Relay[2], LOW);
  delay(1000);
  digitalWrite(Relay[2], HIGH);
  digitalWrite(Relay[3], LOW);
  delay(1000);
  digitalWrite(Relay[3], HIGH);
  digitalWrite(Relay[5], LOW);
  delay(1000);
  digitalWrite(Relay[5], HIGH);
  digitalWrite(Relay[6], LOW);
  delay(1000);
  digitalWrite(Relay[6], HIGH);
  digitalWrite(Relay[7], LOW);
  delay(1000);
  digitalWrite(Relay[7], HIGH);
  digitalWrite(Relay[8], LOW);
  delay(1000);
  digitalWrite(Relay[8], HIGH);
  Serial.println("POST Complete");
}
 

David_AVD

Bite my shiny metal ass!
Community project designer
Generous elf
Joined
Jun 12, 2010
Messages
4,082
Location
Victoria Point (Brisbane)
If you want if to work correctly with the NO contacts (so the lights are off with no signal), you can change a couple of lines:
Code:
      digitalWrite(Relay[b], HIGH); //turn relay on
     }
     else
     {
      digitalWrite(Relay[b], LOW); //else turn it off
can be changed to:
Code:
      digitalWrite(Relay[b], LOW); //turn relay on
     }
     else
     {
      digitalWrite(Relay[b], HIGH); //else turn it off
 

brainless

New elf
Joined
Jan 8, 2015
Messages
10
Code im using now is, the relays are no longer always powered and wired to NC for the load

Code:
/*
Original code created January 4th, 2014 by Claude Heintz http://lx.claudeheintzdesign.com/lxarduino_sketches.html
modified by: Jared Alexander

This code is in the public domain.
sACN E 1.31 is a public standard published by the PLASA technical standards program
http://tsp.plasa.org/tsp/documents/published_docs.php

Requires Arduino Ethernet Shield. Modifed to use the lastest version of Ethernet library included in Arduino 1.6.1. No need to install other libraries. 
Receives E1.31 data (SACN) and ArtNet data for control of relays. This sketch is designed for use with SainSmart Relay boards. 
You can only send the Arduino one protocol (E1.31 or ArtNet) at a time. 
This sketch also includes a power on self test function to make sure everything is hooked up properly.
*/

#include <SPI.h>    //Standard Library     
#include <Ethernet.h> //Standard Library
#include <EthernetUdp.h> //Standard Library


/*  set the desired subnet and universe (first universe is 0)
    sACN starts with universe 1 so subtract 1 from sACN universe
    to get DMX_UNIVERSE.                                           */
#define ARTNET_SUBNET 0 //defualt subnet is 0. Should not need to be changed. 
#define ARTNET_UNIVERSE 41 //first universe being used
#define E131_SUBNET 0 //defualt subnet is 0. Should not need to be changed. 
#define ETHERNET_BUFFER_MAX 640
#define ARTNET_ARTDMX 0x5000
#define ARTNET_ARTPOLL 0x2000
#define ARTNET_PORT 0x1936 //standard port
#define ARTNET_START_ADDRESS 18 //Byte 18 in the packet contains channel 1 values. 
#define E131_PORT 5568 //standard port 
#define E131_START_ADDRESS 126 //Byte 126 in the packet contains channel 1 values. Offset is set to one prior. 
#define STATUS_LED 13 //shows us when we are receiving data
#define SDCARD_CONTROL 4 //set pin 4 to high to disable SD card interface on WiFi shield 
#define NUM_RELAYS 8 //total number of relays used 

int channel; //channel increment 

//Relay Pins array
int Relay[] = {2, 3, 5, 6, 7, 8, 9, 10,};

//Timer Setup
volatile byte currentcounter = 0; //counter for data reception
byte previouscounter = 0; //counter for data reception 
unsigned long currentDelay = 0; //current time value for ArtNet and E1.31 reception

//Ethernet Configuration
byte mac[] = {0x00, 0xDD, 0xEE, 0x01, 0x10, 0x90};
IPAddress ip(192, 168, 1, 213);  //IP address of ethernet shield

// buffer to hold E1.31 and Artnet data
unsigned char packetBuffer[ETHERNET_BUFFER_MAX];

// An EthernetUDP instance to let us send and receive packets over UDP
// aUDP creates a socket for an Art-Net port
// suUDP creates a socket for sACN that is unicast to the ip address
EthernetUDP aUDP;
EthernetUDP suUDP;

void setup() 
{
  pinMode(STATUS_LED, OUTPUT); //Initialize status LED
  pinMode(SDCARD_CONTROL, OUTPUT); //Initialize Pin 4
  digitalWrite(SDCARD_CONTROL, HIGH); //Set pin 4 to high since we are not using the SD Card interface
  for(int a = 0; a < NUM_RELAYS; a++) //loop to initialize relay control pins 
  {
   pinMode(Relay[a], OUTPUT); //initialize relay output pins
   digitalWrite(Relay[a], LOW); //set pins to high for off
  }
  Ethernet.begin(mac,ip);  //Initialize Ethernet shield 
  aUDP.begin(ARTNET_PORT); //Open Artnet Port
  suUDP.begin(E131_PORT); //Open E1.31 Port
  Serial.begin(9600); //Serial for debugging 
  POST(); //Run Power On Self Test Function
  Serial.println("Setup Complete"); //print complete 
}

/* artDMXReceived checks the universe and subnet then
   outputs the data to the relays */

void artDMXReceived(unsigned char* pbuff) 
{
  if ( (pbuff[14] & 0xF) == ARTNET_UNIVERSE ) 
  {
    if ( (pbuff[14] >> 8) == ARTNET_SUBNET ) 
    {
      channel = 0; //reset channel offset to 0 each time through loop
      //loop turns relay on/off based on channel value starting at Artnet start address
      for(int b = 0; b < NUM_RELAYS; b++) 
      {
       if(pbuff[ARTNET_START_ADDRESS + channel] > 127) //if channel value is greater then 127
      {
       digitalWrite(Relay[b], HIGH); //turn relay on 
      } 
      else
      {
       digitalWrite(Relay[b], LOW); //else turn it off 
      }
      channel++; //increase channel offset by 1 each time through for loop
      }
    }
  }
} //end artDMXReceived 

/*  artNetOpCode checks to see that the packet is actually Art-Net
    and returns the opcode telling what kind of Art-Net message it is.  */

int artNetOpCode(unsigned char* pbuff) 
{
  String test = String((char*)pbuff);
  if ( test.equals("Art-Net") ) 
  {
    if ( pbuff[11] >= 14 ) 
    {            //protocol version [10] hi byte [11] lo byte
      return pbuff[9] *256 + pbuff[8];  //opcode lo byte first
    }
  }
 
  return 0;
}

/* sacnDMXReceived checks the universe and subnet then
   outputs the data to relays  */

void sacnDMXReceived(unsigned char* pbuff, int count) 
{
    if ( pbuff[113] == E131_SUBNET ) 
  { 
      int addressOffset = 125; //first 125 bytes of packet are header information
      if ( pbuff[addressOffset] == 0 ) //start code must be 0
      { 
       channel = 0; //reset channel offset to 0 each time through loop
       //loop turns relay on/off based on channel value starting at E1.31 start address
      for(int c = 0; c < NUM_RELAYS; c++)
      {
       if(pbuff[E131_START_ADDRESS + channel] > 127) //if channel value is greater then 127
      {
       digitalWrite(Relay[c], HIGH); //turn relay on
      } 
      else
      {
       digitalWrite(Relay[c], LOW); //turn relay off 
      }
      channel++; //increment channel offset by 1
      }
      }
      } 
    } //end sacnDMXReceived 
   
 
 
//checks to see if packet is E1.31 data
int checkACNHeaders(unsigned char* messagein, int messagelength) 
{
  if ( messagein[1] == 0x10 && messagein[4] == 0x41 && messagein[12] == 0x37) 
  { 
      int addresscount = messagein[123] * 256 + messagein[124]; // number of values plus start code
      return addresscount -1; //Return how many values are in the packet.
    }
  return 0;
}

/************************************************************************
  The main loop checks for and reads packets from the two UDP ethernet
  socket connections.  When a packet is recieved, it is checked to see if
  it is valid and then one of the DMXReceived functions is called, sending
  the DMX values to the output. There also is a timer to run a standby 
  program if no data is received for 30 seconds. 
*************************************************************************/

void loop() 
{
  if(currentcounter != previouscounter) //has the value changed?
  {
    currentDelay = millis(); //store the time since the value has increased 
    previouscounter = currentcounter; //set the previous value equal to the current value
  }
 
  if(millis() - currentDelay > 30000) //is the time since the value changed greater than 30 seconds?
  { 
   digitalWrite(STATUS_LED, HIGH); //turn LED off. Not receiving E1.31 or ArtNet. 
  }
 
  // first check to see if a packet is available on the Art-Net port
  int packetSize = aUDP.parsePacket();
  if( packetSize )
  {
    aUDP.read(packetBuffer, ETHERNET_BUFFER_MAX);
    /* after reading the packet into the buffer, check to make sure
       that it is an Art-Net packet and retrieve the opcode that
       tells what kind of message it is                         */
    int opcode = artNetOpCode(packetBuffer);
    if ( opcode == ARTNET_ARTDMX ) 
    {
      Serial.println("ArtNet Packet Received");
      artDMXReceived(packetBuffer);
      currentcounter++;  //increase counter by 1 each time through 
      digitalWrite(STATUS_LED, HIGH); //turn status LED on
    } 
  } 
    else 
    {
      /* then, if still no packet, check to see if a packet
         is available on the sACN unicastcast port         */
       packetSize = suUDP.parsePacket();
    if( packetSize ) 
    {
      suUDP.read(packetBuffer, ETHERNET_BUFFER_MAX);
      /* after reading the packet into the buffer, check to make sure
       that it is a valid sACN packet.*/
      int count = checkACNHeaders(packetBuffer, packetSize);
      if ( count ) 
      {
        Serial.println("E131 Packet Received");
        sacnDMXReceived(packetBuffer, count);
        currentcounter++;  //increase counter by 1 each time through 
      digitalWrite(STATUS_LED, LOW); //turn status LED on
      }
    }
     
    }
 
} //End loop

//Power on self test function to make sure everything is connected properly. 
void POST()
{
  digitalWrite(Relay[0], HIGH);
  delay(1000);
  digitalWrite(Relay[0], LOW);
  digitalWrite(Relay[1], HIGH);
  delay(1000);
  digitalWrite(Relay[1], LOW);
  digitalWrite(Relay[2], HIGH);
  delay(1000);
  digitalWrite(Relay[2], LOW);
  digitalWrite(Relay[3], HIGH);
  delay(1000);
  digitalWrite(Relay[3], LOW);
  digitalWrite(Relay[5], HIGH);
  delay(1000);
  digitalWrite(Relay[5], LOW);
  digitalWrite(Relay[6], HIGH);
  delay(1000);
  digitalWrite(Relay[6], LOW);
  digitalWrite(Relay[7], HIGH);
  delay(1000);
  digitalWrite(Relay[7], LOW);
  digitalWrite(Relay[8], HIGH);
  delay(1000);
  digitalWrite(Relay[8], LOW);
  Serial.println("POST Complete");
}
 

andy932

New elf
Joined
Dec 10, 2017
Messages
21
hey does anyone know how to set this up in xlights as 1 relay 1 channel. also having problems trying to set it up without messing up the other network pixel controller.
 

Grant Astley

New elf
Joined
Oct 11, 2017
Messages
24
Location
Dubbo NSW
Hi, I know that this is an old thread however I am trying to use the code to control a relay connected to an arduino. I have the following setup
Raspberry pi3 running FPP connected to a F16V3 via Ethernet, the arduino is then connected from the F16V3 to the arduino via Ethernet.
I have assigned an IP address of 10.0.1.120 to the arduino which I can ping from my computer.
I have set up in vixen lights an element called Relay and have assigned it to a new E1.31 controller which I named Arduino. This has been setup as unicast and the ip of the arduino entered. The IO of the arduino in the script has been changed to 22, 24, 26, 28, 30, 32, 34, 36 and the relay connected to pin 22. I have set up on the FPP E1.31 page the universes going to the arduino as unicast and this is universe 11 with 8 channels.
I am however not getting the relay to operate either from the FPP test page or if I run a sequence from Vixen. Am I missing anything at all? can any help / advise be offered
 
Top