Continuing the discussion from Broadcast data to Multiple Cores:
So, I am dredging up this old topic, because I have searched and searched and cannot find what i am doing wrong.
Basically, I have built a set of under-counter LED controllers for the kitchen. They work well, I am using my home automation controller to issue Spark.function()
commands (Lua).
So, I now want to use the installed LED device to issue commands to a child device, so... enter Spark.publish()
and his friendly cousin Spark.subscribe()
. They work brilliantly (bad pun) with a single exception... the approx. one to two seconds it takes for Spark.publish()
to make it's way back to the child device, creating a little lag time (which I know is no big deal) but I'd like to minimize that.
Enter UDP... so I have been trying to take advantage of the lightning fast UDP protocol to transmit the new dim value from the Parent to the Child device. When it works, well it works like magic, almost no perceivable delay. But, It isn't stable. So I am posting my code for possible assistance from the forum members who know about this, which clearly I don't.
Here is the Parent Device code:
#include "Bounce2.h"
#include <application.h>
#define EEPROM_STATE_LOCATION 0
#define FADE_DELAY 20
#define POWER_PIN 2
#define FADE_UP_PIN 3
#define FADE_DOWN_PIN 4
#define DEBUG_ON // Comment out to supress serial output
#define USING_UDP
#ifdef DEBUG_ON
#define DEBUG_PRINT(x) Serial.print(x)
#define DEBUG_PRINTLN(x) Serial.println(x)
#define SERIAL_START(x) Serial.begin(x)
#else
#define DEBUG_PRINT(x)
#define DEBUG_PRINTLN(x)
#define SERIAL_START(x)
#endif
const int ledPin = A6;
const int buttonPin[] = {POWER_PIN, FADE_UP_PIN, FADE_DOWN_PIN};
int oldValue[3];
int currentLevel = 0;
Bounce debouncer[3] = Bounce();
#ifdef USING_UDP
IPAddress slaveIP(192, 168, 1, 255);
unsigned int localPort = 2222;
UDP Udp;
#endif
extern char* itoa(int a, char* buffer, unsigned char radix);
//
void setup()
{
SERIAL_START(115200);
pinMode(ledPin, OUTPUT);
Spark.function("setDimLevel" , incomingDimCommand);
Spark.variable("currentLevel", ¤tLevel, INT);
#ifdef USING_UDP
Udp.begin(localPort);
#endif
DEBUG_PRINTLN("Retreiving saved dim level...");
int storedLevel = EEPROM.read(EEPROM_STATE_LOCATION);
fadeToLevel(storedLevel);
currentLevel = storedLevel;
Spark.publish("newDimValue", String(currentLevel));
for (int i = 0; i < 3; i++)
{
debouncer[i].attach(buttonPin[i]);
debouncer[i].interval(5);
}
}
//
void loop()
{
#ifdef USING_UDP
for (int i = 0; i < 3; i++)
{
debouncer[i].update();
int value = debouncer[i].read();
if (value != oldValue[i])
{
int fadeTarget = 0;
switch (value)
{
case 0:
fadeTarget = currentLevel? 0 : 100;
break;
case 1:
fadeTarget = min(currentLevel + 10, 100);
break;
case 2:
fadeTarget = max(currentLevel - 10, 0);
break;
}
sendFadeTargetAsUDP(value);
//Spark.publish("newDimValue", String(fadeTarget));// debugging
fadeToLevel(fadeTarget);
oldValue[i] = value;
}
}
#endif
}
//
void fadeToLevel(int targetLevel)
{
int delta = (targetLevel - currentLevel) < 0 ? -1 : 1;
while ( currentLevel != targetLevel )
{
currentLevel += delta;
analogWrite( ledPin, (int)(currentLevel / 100.0 * 255) );
delay(FADE_DELAY);
}
}
//
int incomingDimCommand(String params)
{
int value = params.toInt();
value = constrain(value, 0, 100);
#ifdef USING_UDP
sendFadeTargetAsUDP(value);
#else
Spark.publish("newDimValue", String(value));
#endif
fadeToLevel(value);
DEBUG_PRINT("Set incoming dim level to");
DEBUG_PRINTLN(value);
EEPROM.write(EEPROM_STATE_LOCATION, currentLevel);
return value;
}
//
#ifdef USING_UDP
void sendFadeTargetAsUDP(int slaveTarget)
{
DEBUG_PRINTLN("sending message via UDP");
char string1[4] = "";
itoa(slaveTarget, string1, 10); // 10 radix;
Udp.beginPacket(slaveIP, localPort);
Udp.write(string1);
Udp.write('/0');
Udp.endPacket();
}
#endif
and the child:
#define EEPROM_STATE_LOCATION 0
#define FADE_DELAY 20
#define UDP_TX_PACKET_MAX_SIZE 25
//#define DEBUG_ON // Comment out to supress serial output
#define USING_UDP
#ifdef DEBUG_ON
#define DEBUG_PRINT(x) Serial.print(x)#define
#define DEBUG_PRINT2(x,y) Serial.print(x,y)
#define DEBUG_PRINTLN(x) Serial.println(x)
#define SERIAL_START(x) Serial.begin(x)
#else
#define DEBUG_PRINT(x)
#define DEBUG_PRINT2(x,y)
#define DEBUG_PRINTLN(x)
#define SERIAL_START(x)
#endif
const int ledPin = D0;
int currentLevel = 0;
#ifdef USING_UDP
unsigned int localPort = 2222;
UDP udp;
#endif
//
void setup()
{
SERIAL_START(115200);
DEBUG_PRINTLN("Retreiving saved dim level...");
int storedLevel = EEPROM.read(EEPROM_STATE_LOCATION);
fadeToLevel(storedLevel);
currentLevel = storedLevel;
pinMode(D0, OUTPUT);
#ifdef USING_UDP
udp.begin(localPort);
#else
Spark.function("setDimLevel" , incomingDimCommand);
Spark.variable("currentLevel", ¤tLevel, INT);
Spark.subscribe("newDimValue", masterRequest, "<REDACTED>");
Spark.publish("dim_slave", String(currentLevel));
#endif
}
//
void loop()
{
#ifdef USING_UDP
int packetSize = udp.parsePacket();
if (packetSize)
{
// read the packet into packetBufffer
char packetBuffer[UDP_TX_PACKET_MAX_SIZE] = "";
udp.read(packetBuffer, UDP_TX_PACKET_MAX_SIZE);
DEBUG_PRINTLN("Contents:");
DEBUG_PRINTLN(packetBuffer);
int udpValue = atoi(packetBuffer);
fadeToLevel(udpValue);
}
#endif
}
//
void fadeToLevel(int targetLevel)
{
int delta = ( targetLevel - currentLevel ) < 0 ? -1 : 1;
while ( currentLevel != targetLevel )
{
currentLevel += delta;
analogWrite(ledPin, (int)(currentLevel / 100.0 * 255) );
delay(FADE_DELAY);
Spark.process();
}
EEPROM.write(EEPROM_STATE_LOCATION, currentLevel);
}
//
int incomingDimCommand(String params)
{
int value = params.toInt();
value = constrain(value, 0, 100);
fadeToLevel(value);
DEBUG_PRINT("Set incoming dim level to");
DEBUG_PRINTLN(value);
return value;
}
#ifdef USING_UDP
#else
void masterRequest(const char *event, const char *data)
{
String params = String(data);
int value = params.toInt();
value = constrain(value, 0, 100);
fadeToLevel(value);
Spark.publish("dim_slave_Subscribe", String(currentLevel));// test
DEBUG_PRINT("Set incoming dim level to");
DEBUG_PRINTLN(value);
}
#endif