Home Automation blog

Skip to Content

Controllable downlights part two

Posted by Chris

Date posted:

Node-RED flow of my home-kit to RGB node

In my original post I played around with a now discontinued tri-color (warm/cool/natural whites) LED downlight. And a DMX decoder LED driver, but was unable to obtain the correct DMX address writer and the seller wasn't responding. So I've moved onto RGB downlights and dip-switch address DMX decoder/driver - linked below.

Hardware

Software

I've released my first Node JS package, for Node-RED. It converts HomeKit's light accessory's HSB values into RGB values. View on Node-RED website. To be used by the Arduino DMX controller.

Node-RED function node

Take the three RGB values and pad them into 3 digit values for use with the Arduino. And set the starting address. In this example it's address 001.

msg.payload[0] =  String(msg.payload[0]).padStart(3, '0');
msg.payload[1] =  String(msg.payload[1]).padStart(3, '0');
msg.payload[2] =  String(msg.payload[2]).padStart(3, '0');

msg.payload = "001" + msg.payload[0] + "" + msg.payload[1] + "" + msg.payload[2];

return msg;

Arduino code

Convert MQTT string into 4 integer values. First address, Red value, Green value, Blue value.

Eg: 001255255255 = address: 001, red: 255, green: 255, blue: 255. Which assumes the addresses of 001, 002, 003.

#include <Ethernet.h>
#include <PubSubClient.h>
#include <DmxSimple.h>


// Ethernet https://www.miniwebtool.com/mac-address-generator/
byte device_mac[] = {0x16,0xB8,0x90,0x93,0x56,0xDA};
EthernetClient device;


// MQTT
IPAddress mqtt_ip(XXX, XXX, XXX, XXX);
PubSubClient mqtt(device);
String mqtt_client = "dmx";
const char mqtt_user[] = "XXXX";
const char mqtt_pass[] = "XXXX";
const char mqtt_sub[] = "device/house/light";


void setup()
{
	// Configure DMX
	DmxSimple.usePin(4);
	DmxSimple.maxChannel(512);

	// Interface with the DMX shield on I/O pin 2, instead of TX/TR
	pinMode (2, OUTPUT);
	digitalWrite (2, HIGH);

	// Just for visual testing of network connection
	// All downlights 1% while we wait for network connection
	for (int i = 0; i < 512; i++)
	{
		DmxSimple.write(i, 1);
	}

	// Wait for network connection
	while (Ethernet.begin(device_mac) == 0)
	{
		delay(1000);
	}

	// Initializes the pseudo-random number generator
	randomSeed(micros());

	// Configure MQTT
	mqtt.setServer(mqtt_ip, 1883);
	mqtt.setCallback(mqttReceive);

	// Connected to network. All downlights off
	for (int i = 0; i < 512; i++)
	{
		DmxSimple.write(i, 0);
	}
}


void loop()
{
	Ethernet.maintain();

	if (!mqtt.connected())
	{
		mqttReconnect();
  	}

	mqtt.loop();
}


void mqttReconnect()
{
	while (!mqtt.connected())
	{
		mqtt_client += String(random(0xffff), HEX);

		if (mqtt.connect(mqtt_client.c_str(), mqtt_user, mqtt_pass))
		{
			mqtt.subscribe(mqtt_sub);
		}
		else
		{
			delay(5000);
		}
	}
}


void mqttReceive(char* topic, byte* payload, unsigned int leng)
{
	char channel[4] = "";
	char val1[4] = "";
	char val2[4] = "";
	char val3[4] = "";

	// Determine starting channel value, eg: 001 - 512
	for (int i = 0; i < 3; i++)
	{
		 channel[i] = payload[i];
	}
	channel[3] = "\0";

	// Determine first channel's value. Eg: 000 - 255
	for (int i = 3; i < 6; i++)
	{
		 val1[i - 3] = payload[i];
	}
	val1[3] = "\0";

	// Determine second channel's value. Eg: 000 - 255
	for (int i = 6; i < 9; i++)
	{
		 val2[i - 6] = payload[i];
	}
	val2[3] = "\0";

	// Determine third channel's value. Eg: 000 - 255
	for (int i = 9; i < 12; i++)
	{
		 val3[i - 9] = payload[i];
	}
	val3[3] = "\0";

	// Convert to int
	int c = atoi(channel);
	int v1 = atoi(val1);
	int v2 = atoi(val2);
	int v3 = atoi(val3);

	// Apply the three channels
	DmxSimple.write(c, v1);
	DmxSimple.write(c + 1, v2);
	DmxSimple.write(c + 2, v3);
}

View similar posts categorised as: Arduino Node RED HomeKit