Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 51 additions & 0 deletions include/main.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
#ifndef MAIN_H
#define MAIN_H

#include <Arduino.h>
#include <SPI.h>
#include <Ethernet.h>
#include <EthernetUdp.h>
#include <ArtnetEther.h>
#include <FastLED.h>

// Config switches
#define DEBUG 0 // 1: DEBUG at 115200, 0: No DEBUG
#define DHCP 1 // 1: Use DHCP, 0: Use static IP as defined in main
#define TEST_MODE 1 // 1: Just run some LEDs on Red, 0: normal behaviour

// Pin definitions
#define WS2812_DATA_PIN 6
#define NETWORK_STATUS_PIN 4
#define LED_WRITE_STATUS_PIN 3

// LED Configuration
#define NUM_LEDS 33
#define ARTNET_PORT 6454
#define START_UNIVERSE 0 // we may not want to begin on universe 0 (remember that artnet is 0-indexed)
#define LEDS_PER_UNIVERSE 170
#define CHANNELS_PER_UNIVERSE (LEDS_PER_UNIVERSE * 3)

// Calculated constants
extern const uint8_t NUM_UNIVERSES;
extern const uint8_t ALL_UNI_MASK;

// Network configuration
extern byte mac[];
extern IPAddress ip;
extern ArtnetEtherReceiver artnet;

// LED data
extern CRGB leds[];
extern uint8_t universesReceived;
extern unsigned long lastShowTime;
extern const unsigned long MIN_SHOW_INTERVAL;

// Function declarations
void led_status(String led, bool state);
void artnet_callback(const uint8_t *data, uint16_t size, const ArtDmxMetadata &metadata, const ArtNetRemoteInfo &remote);
void led_hello();
void led_oh_shit(int led_pin);
void init_leds();
void init_networking();

#endif // MAIN_H
3 changes: 2 additions & 1 deletion platformio.ini
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,5 @@
platform = atmelavr
board = uno
framework = arduino
monitor_speed = 115200
upload_protocol = usbtiny
upload_flags = -e
156 changes: 123 additions & 33 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,44 +4,36 @@
// All Rights Reserved 2025
// Licensed under the GNU GPL License.

#define DEBUG 1 // 1: DEBUG at 115200, 0: No DEBUG

// Required libraries
#include <SPI.h>
#include <Ethernet.h>
#include <EthernetUdp.h>
#include <ArtnetEther.h>
#include <FastLED.h>

// Defined constants
#define LED_PIN 6
#define NUM_LEDS 33
#define ARTNET_PORT 6454
#define START_UNIVERSE 0 // we may not want to begin on universe 0 (remember that artnet is 0-indexed)
#define LEDS_PER_UNIVERSE 170
#define CHANNELS_PER_UNIVERSE (LEDS_PER_UNIVERSE * 3)

// Tracking for smart refresh
#include "main.h"

// Global variable definitions
const uint8_t NUM_UNIVERSES = (NUM_LEDS + LEDS_PER_UNIVERSE - 1) / LEDS_PER_UNIVERSE;
const uint8_t ALL_UNI_MASK = (1 << NUM_UNIVERSES) - 1;


// Static IP and MAC address
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(192, 168, 1, 50); // Set your desired static IP here
IPAddress ip(192, 168, 1, 50);
ArtnetEtherReceiver artnet;

/// @brief Array to hold the LED data
CRGB leds[NUM_LEDS];
uint8_t universesReceived = 0;
unsigned long lastShowTime = 0;
const unsigned long MIN_SHOW_INTERVAL = 8; // ~125fps max

void artnet_callback(
const uint8_t *data, uint16_t size,
const ArtDmxMetadata &metadata,
const ArtNetRemoteInfo &remote
) {
void led_status(String led, bool state) {
#if DEBUG
Serial.print(led);
Serial.print(" LED is now ");
Serial.println(state ? "ON" : "OFF");
#endif

if (led == "network") {
digitalWrite(NETWORK_STATUS_PIN, state ? HIGH : LOW);
} else if (led == "led_write") {
digitalWrite(LED_WRITE_STATUS_PIN, state ? HIGH : LOW);
}
}

void artnet_callback( const uint8_t *data, uint16_t size, const ArtDmxMetadata &metadata, const ArtNetRemoteInfo &remote ) {
uint8_t rel = metadata.universe - START_UNIVERSE;
if (rel >= NUM_UNIVERSES) return;

Expand All @@ -62,27 +54,115 @@ void artnet_callback(
Serial.println(universesReceived, HEX);
#endif

if (universesReceived == ALL_UNI_MASK &&
now - lastShowTime >= MIN_SHOW_INTERVAL) {

if (universesReceived == ALL_UNI_MASK && now - lastShowTime >= MIN_SHOW_INTERVAL) {
led_status("led_write", true);
FastLED.show();
lastShowTime = now;
universesReceived = 0;
led_status("led_write", false);
}
}

void led_hello() {
// do a little dance to say hello
digitalWrite(LED_WRITE_STATUS_PIN, HIGH);
delay(200);
digitalWrite(LED_WRITE_STATUS_PIN, LOW);
delay(200);
digitalWrite(LED_WRITE_STATUS_PIN, HIGH);
delay(200);
digitalWrite(LED_WRITE_STATUS_PIN, LOW);
delay(200);

digitalWrite(NETWORK_STATUS_PIN, HIGH);
delay(200);
digitalWrite(NETWORK_STATUS_PIN, LOW);
delay(200);
digitalWrite(NETWORK_STATUS_PIN, HIGH);
delay(200);
digitalWrite(NETWORK_STATUS_PIN, LOW);
delay(200);

digitalWrite(LED_WRITE_STATUS_PIN, HIGH);
digitalWrite(NETWORK_STATUS_PIN, HIGH);
delay(200);
digitalWrite(LED_WRITE_STATUS_PIN, LOW);
digitalWrite(NETWORK_STATUS_PIN, LOW);
delay(200);
digitalWrite(LED_WRITE_STATUS_PIN, HIGH);
digitalWrite(NETWORK_STATUS_PIN, HIGH);
delay(200);
digitalWrite(LED_WRITE_STATUS_PIN, LOW);
digitalWrite(NETWORK_STATUS_PIN, LOW);
delay(200);
digitalWrite(LED_WRITE_STATUS_PIN, HIGH);
digitalWrite(NETWORK_STATUS_PIN, HIGH);
delay(200);
digitalWrite(LED_WRITE_STATUS_PIN, LOW);
digitalWrite(NETWORK_STATUS_PIN, LOW);
delay(200);
digitalWrite(LED_WRITE_STATUS_PIN, HIGH);
digitalWrite(NETWORK_STATUS_PIN, HIGH);
delay(200);
digitalWrite(LED_WRITE_STATUS_PIN, LOW);
digitalWrite(NETWORK_STATUS_PIN, LOW);
delay(200);
}

void led_oh_shit(int led_pin) {
while(1) {
digitalWrite(led_pin, HIGH);
delay(250);
digitalWrite(led_pin, LOW);
delay(250);
}
}

void init_leds() {
FastLED.addLeds<WS2812B, LED_PIN, GRB>(leds, NUM_LEDS);
// initialize FastLED
FastLED.addLeds<WS2812B, WS2812_DATA_PIN, GRB>(leds, NUM_LEDS);
FastLED.setMaxRefreshRate(0); // Remove artificial frame rate limit
FastLED.setDither(false);
FastLED.setCorrection(UncorrectedColor);
FastLED.clear();
FastLED.show();

// initialize status pins
pinMode(NETWORK_STATUS_PIN, OUTPUT);
pinMode(LED_WRITE_STATUS_PIN, OUTPUT);

led_hello();
}

void init_networking() {
Ethernet.begin(mac, ip);
if (DHCP) {
if (Ethernet.begin(mac)) {
// DHCP configured successfully :)
} else {
// shit shit shit shit shit
led_oh_shit(NETWORK_STATUS_PIN);
}
} else {
Ethernet.begin(mac, ip);
}

if (Ethernet.linkStatus() == LinkON) {
led_status("network", true);
} else {
led_oh_shit(NETWORK_STATUS_PIN);
}

#if DEBUG
Serial.print("Ethernet initialized with IP: ");
Serial.println(Ethernet.localIP());
Serial.print("Subnet Mask: ");
Serial.println(Ethernet.subnetMask());
Serial.print("Gateway IP: ");
Serial.println(Ethernet.gatewayIP());
Serial.print("Link Status: ");
Serial.println(Ethernet.linkStatus() == LinkON ? "LinkON" : "LinkOFF");
#endif

delay(100);
artnet.begin(ARTNET_PORT);
artnet.subscribeArtDmx(artnet_callback);
Expand All @@ -106,5 +186,15 @@ void setup() {
}

void loop() {
artnet.parse();
if (TEST_MODE) {
for (int i = 0; i < NUM_LEDS; i++) {
leds[i] = CRGB::Red;
}

FastLED.show();
while (1); // halt!

} else {
artnet.parse();
}
}
Loading