Hi, I'm trying to implement DMX into this fantastic plugin.
The main problem with my modification below is once I set a new value for the DMX-RGB the main loop waits until the fade is done. How can I rebuild the code so the fade process can work as another "thread"?
The optional need is to have multiple RGB DMX channels that can be controlled from HS, ex send 50,30,70,x to channel 1,2,3 where x is the fadetime. Direct after this is sent I would like the api to be ready to get new data for the other channels even if the fade is not ready for the first call. Is this possible?
The main problem with my modification below is once I set a new value for the DMX-RGB the main loop waits until the fade is done. How can I rebuild the code so the fade process can work as another "thread"?
The optional need is to have multiple RGB DMX channels that can be controlled from HS, ex send 50,30,70,x to channel 1,2,3 where x is the fadetime. Direct after this is sent I would like the api to be ready to get new data for the other channels even if the fade is not ready for the first call. Is this possible?
PHP Code:
//For serial set to 0 and for Ethernet set to 1
#define ISIP 1
//Do NOT modify these
#if ISIP == 1
#include <EEPROM.h>
#include <SPI.h>
#include <Ethernet.h>
#include <EthernetUdp.h>
#endif
/************************************************************
*Arduino to Homeseer 3 Plugin API written by Enigma Theatre.*
* V1.0.0.81 *
* *
*******Change the values below only*************************
*/
#include <Conceptinetics.h>
//------------------------------------------------------
#define DMX_MASTER_CHANNELS 100
#define RXEN_PIN 2
DMX_Master dmx_master ( DMX_MASTER_CHANNELS, RXEN_PIN );
//------------------------------------------------------
//Address of the board.
const byte BoardAdd = 1;
#if ISIP == 1
// Enter a MAC address and IP address for your board below.
byte mac[] = {0x00, 0xAA, 0xBB, 0xCC, 0xDE, 0x01};
// The IP address will be dependent on your local network.
IPAddress ip(192,168,2,143); //IP entered in HS config.
const unsigned int localPort = 8901; //port entered in HS config.
IPAddress HomeseerIP(192,168,2,15); //Homeseer IP address
IPAddress ServerIP(EEPROM.read(2),EEPROM.read(3),EEPROM.read(4),EEPROM.read(5));
byte EEpromVersion = EEPROM.read(250);
#endif
//************Do not change anything in Here*****************
int FromHS[10]; // *
boolean IsConnected = false; // *
#if ISIP == 1 // *
char packetBuffer[UDP_TX_PACKET_MAX_SIZE]; // *
EthernetUDP Udp; // *
const unsigned int ServerPort = 8888; // *
#endif // *
void(* resetFunc) (void) = 0; // *
//***********************************************************
int black[3] = { 0, 0, 0 };
int redVal = black[0];
int grnVal = black[1];
int bluVal = black[2];
int wait = 1;
int prevR = redVal;
int prevG = grnVal;
int prevB = bluVal;
void setup() {
HSSetup();
//************************
//Add YOUR SETUP HERE;
//************************
dmx_master.enable ();
dmx_master.setChannelRange ( 2, 25, 127 );
int wait = 5; // 10ms internal crossFade delay; increase for slower fades
int hold = 200; // Optional hold when a color is complete, before the next crossFade
}
void loop() {
#if ISIP == 1
IsUDP();
#endif
//************************
//Add YOUR CODE HERE;
//************************
/* To Send Data to Homeseer use SendToHS(Device,Value)
Eg.. SendToHS(1,200); where 1 is the API device in homeseer and 200 is the value to send
To Recieve data from Homeseer look up the FromHS array that is updated when the device value changes.
Eg.. FromHS[5] would be the data from API Output device 5
All code that is located just below this block will execute regardless of connection status!
You can include SendToHS() calls, however when there isn't an active connection, it will just return and continue.
If you only want code to execute when HomeSeer is connected, put it inside the if statement below.
*/
/*Execute regardless of connection status*/
if (IsConnected == true) {
if (1==1) {
}
/*Execute ONLY when HomeSeer is connected*/
int rgb[3] = { FromHS[0], FromHS[1], FromHS[2] };
crossFade(rgb);
}
else
{
dmx_master.setChannelValue ( 10, 0 );
dmx_master.setChannelValue ( 11, 0 );
dmx_master.setChannelValue ( 12, 0 );
}
}
//----DMX Crossfade functions
int calculateStep(int prevValue, int endValue) {
int step = endValue - prevValue;
if (step) {
step = 1020/step;
}
return step;
}
int calculateVal(int step, int val, int i) {
if ((step) && i % step == 0) {
if (step > 0) {
val += 1;
}
else if (step < 0) {
val -= 1;
}
}
if (val > 255) {
val = 255;
}
else if (val < 0) {
val = 0;
}
return val;
}
void crossFade(int color[3]) {
int R = (color[0] * 255) / 100;
int G = (color[1] * 255) / 100;
int B = (color[2] * 255) / 100;
int stepR = calculateStep(prevR, R);
int stepG = calculateStep(prevG, G);
int stepB = calculateStep(prevB, B);
if (stepR > 0 || stepG >0 || stepB > 0) {
}else{
return;
}
for (int i = 0; i <= 1020; i++) {
redVal = calculateVal(stepR, redVal, i);
grnVal = calculateVal(stepG, grnVal, i);
bluVal = calculateVal(stepB, bluVal, i);
dmx_master.setChannelValue ( 10, redVal );
dmx_master.setChannelValue ( 11, grnVal );
dmx_master.setChannelValue ( 12, bluVal );
delay(wait);
}
prevR = redVal;
prevG = grnVal;
prevB = bluVal;
}
const char* Version = "API1.0.0.81";
byte Byte1,Byte2,Byte3;
int Byte4,Byte5;
void HSSetup() {
#if ISIP == 1
if (EEpromVersion!=22) {
ServerIP=HomeseerIP;
EEPROM.write(2,ServerIP[0]);
EEPROM.write(3,ServerIP[1]);
EEPROM.write(4,ServerIP[2]);
EEPROM.write(5,ServerIP[3]);
EEPROM.write(250,22); //Store the version where the eeprom data layout was last changed
EEpromVersion=22;
}
Ethernet.begin(mac,ip);
Udp.begin(localPort);
Udp.setTimeout(0);
delay(1000);
SendConnect();
#else
Serial.begin(115200);
Serial.flush();
Serial.setTimeout(0);
delay(1000);
Serial.print("Connect ");
Serial.println(BoardAdd);
#endif
IsConnected = false;
}
void SendConnect()
{
#if ISIP == 0
Serial.print("Connect ");
Serial.println(BoardAdd);
#else
Udp.beginPacket(ServerIP,ServerPort); //First send a connect packet to the dynamic IP stored in eeprom
Udp.print("Connect ");
Udp.print(BoardAdd);
Udp.endPacket();
if (ServerIP!=HomeseerIP) {
Udp.beginPacket(HomeseerIP,ServerPort); //Then if the stored value doesn't match the pre-specified one, send a connect packet there also
Udp.print("Connect ");
Udp.print(BoardAdd);
Udp.endPacket();
}
#endif
}
#if ISIP == 1
void IsUDP(){
int packetSize = Udp.parsePacket();
if(packetSize)
{
IPAddress remote = Udp.remoteIP();
Byte1 =Udp.parseInt();
Udp.read();
Byte2 =Udp.read();
Byte3 =Udp.parseInt();
Byte4 =Udp.parseInt();
Byte5 =Udp.parseInt();
DataEvent();
}
}
#else
void serialEvent() {
while (Serial.available() > 0) {
delay(17);
Byte1 = Serial.parseInt();
Serial.read();
Byte2 = Serial.read();
Byte3 = Serial.parseInt();
Byte4 = Serial.parseInt();
Byte5 = Serial.parseInt();
DataEvent();
}
}
#endif
/*
Used Data Input Cases
D Disconnect
r reset
K Keepalive
O PinMode Output Set
d Input debounce time set
C Connect request
c Connection established - report current status
*/
void DataEvent() {
if (Byte1 == BoardAdd) {
switch (Byte2) {
case 'c':
IsConnected = true;
#if ISIP == 1
if (Udp.remoteIP() != ServerIP) {
ServerIP=Udp.remoteIP();
EEPROM.write(2,ServerIP[0]);
EEPROM.write(3,ServerIP[1]);
EEPROM.write(4,ServerIP[2]);
EEPROM.write(5,ServerIP[3]);
}
#endif
break;
case 'C':
#if ISIP == 1
Udp.beginPacket(Udp.remoteIP(), ServerPort);
Udp.print("Version ");
Udp.print(BoardAdd);
Udp.print(" ");
Udp.print(Version);
Udp.println(" HS3");
Udp.endPacket();
Udp.beginPacket(Udp.remoteIP(), ServerPort);
delay(100);
Udp.print("Connected ");
Udp.println(BoardAdd);
Udp.endPacket();
#else
Serial.print("Version ");
Serial.print(BoardAdd);
Serial.print(" ");
Serial.print(Version);
Serial.println(" HS3");
delay(100);
Serial.print("Connected ");
Serial.println(BoardAdd);
#endif
delay(100);
IsConnected = false;
break;
case 'K':
delay(200);
#if ISIP == 1
Udp.beginPacket(Udp.remoteIP(), ServerPort);
Udp.print("Alive ");
Udp.println(BoardAdd);
Udp.endPacket();
if (Udp.remoteIP() != ServerIP) {
ServerIP=Udp.remoteIP();
EEPROM.write(2,ServerIP[0]);
EEPROM.write(3,ServerIP[1]);
EEPROM.write(4,ServerIP[2]);
EEPROM.write(5,ServerIP[3]);
}
#else
Serial.print("Alive ");
Serial.println(BoardAdd);
#endif
break;
case 'r':
delay(200);
resetFunc(); //call reset
break;
case 'O':
FromHS[Byte3] = Byte4;
break;
case 'D':
IsConnected = false;
break;
}
}
}
void SendToHS(byte Device, long Data){
if (IsConnected == true) {
#if ISIP == 1
Udp.beginPacket(Udp.remoteIP(), ServerPort);
Udp.print(BoardAdd);
Udp.print(" API ");
Udp.print(Device);
Udp.print(" ");
Udp.print(Data);
Udp.endPacket();
#else
Serial.print(BoardAdd);
Serial.print(" API ");
Serial.print(Device);
Serial.print(" ");
Serial.println(Data);
#endif
}
}
void SendToHS(byte Device, int Data){
if (IsConnected == true) {
#if ISIP == 1
Udp.beginPacket(Udp.remoteIP(), ServerPort);
Udp.print(BoardAdd);
Udp.print(" API ");
Udp.print(Device);
Udp.print(" ");
Udp.print(Data);
Udp.endPacket();
#else
Serial.print(BoardAdd);
Serial.print(" API ");
Serial.print(Device);
Serial.print(" ");
Serial.println(Data);
#endif
}
}
void SendToHS(byte Device, float Data){
if (IsConnected == true) {
#if ISIP == 1
Udp.beginPacket(Udp.remoteIP(), ServerPort);
Udp.print(BoardAdd);
Udp.print(" API ");
Udp.print(Device);
Udp.print(" ");
Udp.print(Data);
Udp.endPacket();
#else
Serial.print(BoardAdd);
Serial.print(" API ");
Serial.print(Device);
Serial.print(" ");
Serial.println(Data);
#endif
}
}
Comment