chrisstaite / ArduinoArtNet

ArtNet library for Arduino
GNU General Public License v3.0
16 stars 4 forks source link

ws2801 support #1

Closed unmanagedtn closed 10 years ago

unmanagedtn commented 11 years ago

Could you modify to support the more common ws2801?

chrisstaite commented 10 years ago

The library does not "support" any LEDs. See the FastLED project for how to modify it for use with any of the common LEDs (such as WS2801).

folny commented 10 years ago

Hello

I would like to ask whether it would be put into the sketch to add new DMX universe to control other Led Pixels.

chrisstaite commented 10 years ago

The protocol supports up to 4 universes before having to run multiple instances. Just change the universes parameter for the constructor.

folny commented 10 years ago

Thank you for your answer, please you can write an example of how it should I do because I'm not sure how exactly I have to write it.

folny commented 10 years ago

I modified the sketch library FastLed code works great but I can not seem to add another port to control other LED pixels Please advise me how to edit the sketch ?.

include

include

include

include "FastLED.h"

define NUM_LEDS 170

define DEFAULT_START_ADDRESS 0

CRGB ledsPort1[NUM_LEDS]; CRGB ledsPort2[NUM_LEDS];

// Set a different MAC address for each... static byte mymac[] = { 0x74, 0x69, 0x69, 0x2D, 0x30, 0x32 }; byte Ethernet::buffer[600]; // tcp/ip send and receive buffer

ArtNet *artnet;

struct Config { IPConfiguration iptype; byte ip[4]; byte gateway[4]; unsigned short connectedLEDs; unsigned short startAddress; byte valid; } config;

// Calling 0 breaks the processor causing it to soft reset void(* resetFunc) (void) = 0;

static void saveConfig() { for (unsigned short i = 0; i < sizeof(config); ++i) { EEPROM.write(i, ((byte*)&config)[i]); } }

static void loadConfig() { for (unsigned short i = 0; i < sizeof(config); ++i) { ((byte*)&config)[i] = EEPROM.read(i); } if (config.valid != 252) { // Load defaults config.iptype = DHCP; config.connectedLEDs = NUM_LEDS; config.startAddress = DEFAULT_START_ADDRESS; config.valid = 252; saveConfig(); } }

static void setIP(IPConfiguration iptype, const char ip, const char subnet) { config.iptype = iptype; memcpy(config.ip, ip, 4); // Subnet too?? // What about the gateway - not really important for ArtNet! saveConfig(); // Restart the chip to load the new configuration resetFunc(); }

static void artSend(byte length, word sport, byte dip, word dport) { ether.sendUdp((char)Ethernet::buffer + UDP_DATA_P, length, sport, dip, dport); }

static void callback(unsigned short port, const char buffer, unsigned short length) { if (length < config.startAddress) return; if (port != 0) return; length -= config.startAddress; buffer = buffer + config.startAddress; length = length / 3; if (length > config.connectedLEDs) length = config.connectedLEDs; for (int i = 0; i < length; ++i) { ledsPort1[i].r = buffer[i * 3]; ledsPort1[i].g = buffer[i * 3 + 1]; ledsPort1[i].b = buffer[i \ 3 + 2];

} FastSPI_LED.show(); }

static void artnetPacket(word port, byte ip[4], const char *data, word len) { artnet->ProcessPacket(ip, port, data, len); }

void setup() { Serial.begin(57600); Serial.println(F("\nBooting"));

// Load configuration Serial.println(F("Loading configuration")); loadConfig();

// Setup LEDS Serial.println(F("Configuring LEDs"));

FastLED.addLeds<WS2812B, 2, RGB>(ledsPort1, NUM_LEDS); FastLED.addLeds<WS2812B, 3, RGB>(ledsPort2, NUM_LEDS);

Serial.println(F("Initialising LEDs"));

Serial.println(F("Clearing LEDs")); memset(ledsPort1, 0, config.connectedLEDs * 3); memset(ledsPort2, 0, config.connectedLEDs * 3);

FastLED.show();

// Startup ethernet Serial.println(F("Initialising ENC28J60")); if (ether.begin(sizeof(Ethernet::buffer), mymac) == 0) Serial.println(F("Failed to access Ethernet controller"));

// Configure IP address if (config.iptype == DHCP) { Serial.println(F("Configuring node as DHCP")); if (!ether.dhcpSetup()) Serial.println(F("DHCP Failed...")); ether.printIp("IP: ", ether.myip); ether.printIp("GW: ", ether.gwip); } else if (config.iptype == CUSTOM) { Serial.println(F("Configuring node with custom IP")); ether.staticSetup(config.ip, config.gateway); ether.printIp("IP: ", ether.myip); ether.printIp("GW: ", ether.gwip); } else if (config.iptype == PRIMARY) { byte ip[] = {2, mymac[3]+OEM_HI+OEM_LO, mymac[4], mymac[5]}; byte gwy[] = {2, 0, 0, 1}; Serial.println(F("Configuring node with primary IP")); ether.staticSetup(ip, gwy); ether.printIp("IP: ", ether.myip); ether.printIp("GW: ", ether.gwip); } else if (config.iptype == SECONDARY) { byte ip[] = {10, mymac[3]+OEM_HI+OEM_LO, mymac[4], mymac[5]}; byte gwy[] = {10, 0, 0, 1}; Serial.println(F("Configuring node with secondary IP")); ether.staticSetup(ip, gwy); ether.printIp("IP: ", ether.myip); ether.printIp("GW: ", ether.gwip); } else { Serial.println(F("loadConfig() is doing its job wrong")); }

Serial.println(F("Configuring ArtNet")); artnet = new ArtNet(ether.myip, mymac, config.iptype == DHCP, sizeof(config) + 1, Ethernet::buffer + UDP_DATA_P, sizeof(Ethernet::buffer) - UDP_DATA_P, setIP, artSend, callback, 1);

// Register listener Serial.println(F("Listening on ArtNet")); /* Also need to change line 110 of tcpip.cpp to: (memcmp(gPB + IP_DST_P, EtherCard::myip, 4) == 0 || gPB[IP_DST_P + 3] == 0xff); */ ether.enableBroadcast(); ether.udpServerListenOnPort(&artnetPacket, UDP_PORT_ARTNET); }

char statusPage[] PROGMEM = "HTTP/1.0 200 Ok\r\n" "Content-Type: text/html\r\n" "Pragma: no-cache\r\n" "\r\n" "" "" "ArtNet Node Configuration" "" "" "

ArtNet Node Configuration

" "

Packets: %d (%d failed)

" "

IP Configuration

" "

ArtNet Configuration

" "

LED Configuration

" "" "";

char ipPage[] PROGMEM = "HTTP/1.0 200 Ok\r\n" "Content-Type: text/html\r\n" "Pragma: no-cache\r\n" "\r\n" "" "" "ArtNet Node" "" "" "

IP Configuration

" "Back

" "

" "IP Type:

" "IP:

" "" "

" "" "";

char artnetPage[] PROGMEM = "HTTP/1.0 200 Ok\r\n" "Content-Type: text/html\r\n" "Pragma: no-cache\r\n" "\r\n" "" "" "ArtNet Node" "" "" "

ArtNet Configuration

" "Back

" "

" "Short Name:

" "Long Name:

" "ArtNet Subnet:

" "Universe:

" "" "

" "" "";

char ledPage[] PROGMEM = "HTTP/1.0 200 Ok\r\n" "Content-Type: text/html\r\n" "Pragma: no-cache\r\n" "\r\n" "" "" "ArtNet Node" "" "" "

Picel Configuration

" "Back

" "

"

  "Connected LEDs:<input type='text' name='leds' value='%d'><p/>"
  "Start Address:<input type='text' name='address' value='%d'><p/>"

"Pixel Type:

"
"" "

" "" "";

void sendHomePage() { unsigned short len = sprintf_P((char*)ether.tcpOffset(), statusPage, artnet->GetPacketCount(), artnet->GetFailCount()); ether.httpServerReply(len); }

void sendIPPage() { unsigned short len = sprintf_P((char*)ether.tcpOffset(), ipPage, config.iptype == DHCP ? " selected='selected'" : "", config.iptype == PRIMARY ? " selected='selected'" : "", config.iptype == SECONDARY ? " selected='selected'" : "", config.iptype == CUSTOM ? " selected='selected'" : "", ether.myip[0], ether.myip[1], ether.myip[2], ether.myip[3]); ether.httpServerReply(len); }

void sendArtNetPage() { char shortName[19] = {0}; char longName[65] = {0}; artnet->GetShortName(shortName); artnet->GetLongName(longName); unsigned short len = sprintf_P((char*)ether.tcpOffset(), artnetPage, shortName, longName, artnet->GetSubnet(), artnet->GetInputUniverse(0)); ether.httpServerReply(len); }

void sendLEDPage() { unsigned short len = sprintf_P((char*)ether.tcpOffset(), ledPage, config.connectedLEDs, config.startAddress + 1); ether.httpServerReply(len); }

static int getIntArg(const char* data, const char* key, int value =-1) { char temp[10]; if (ether.findKeyVal(data, temp, sizeof temp, key) > 0) value = atoi(temp); return value; }

static void setIpArg(const char data, const char key) { char ip[16]; if (ether.findKeyVal(data, ip, sizeof(ip), key) > 0) { byte i; byte parsedIp[4]; char *p = strtok(ip, "."); if (p == NULL) return; parsedIp[0] = atoi(p); for (i = 1; i < 4; ++i) { p = strtok(NULL, "."); if (p == NULL) return; parsedIp[i] = atoi(p); } memcpy(config.ip, parsedIp, 4); } }

static void setShortName(const char data, const char key) { char shortName[19]; if (ether.findKeyVal(data, shortName, sizeof(shortName), key) > 0) { ether.urlDecode(shortName); artnet->SetShortName(shortName); } }

static void setLongName(const char data, const char key) { char longName[65]; if (ether.findKeyVal(data, longName, sizeof(longName), key) > 0) { ether.urlDecode(longName); artnet->SetLongName(longName); } }

void loop() { word pos = 0; if ((pos = ether.packetLoop(ether.packetReceive()))) { if (strncmp("GET / ", (const char )(Ethernet::buffer + pos), 6) == 0) { // Page emmited sendHomePage(); } else if (strncmp("GET /ip ", (const char )(Ethernet::buffer + pos), 8) == 0) { // Page emmited sendIPPage(); } else if (strncmp("GET /artnet ", (const char )(Ethernet::buffer + pos), 12) == 0) { // Page emmited sendArtNetPage(); } else if (strncmp("GET /led ", (const char )(Ethernet::buffer + pos), 9) == 0) { // Page emmited sendLEDPage(); } else if (strncmp("GET /artnet?", (const char )(Ethernet::buffer + pos), 12) == 0) { // Save settings artnet->SetInputUniverse(0, getIntArg((const char )(Ethernet::buffer + pos + 11), "universe", artnet->GetInputUniverse(0))); artnet->SetSubnet(getIntArg((const char )(Ethernet::buffer + pos + 11), "subnet", artnet->GetSubnet())); setShortName((const char )(Ethernet::buffer + pos + 11), "shortname"); setLongName((const char *)(Ethernet::buffer + pos + 11), "longname");

  // Send page with new settings
  sendArtNetPage();
}  else if (strncmp("GET /led?", (const char *)(Ethernet::buffer + pos), 9) == 0) {
  // Save settings
  config.connectedLEDs = getIntArg((const char *)(Ethernet::buffer + pos + 11), "leds", config.connectedLEDs);
  config.startAddress = getIntArg((const char *)(Ethernet::buffer + pos + 11), "address", config.startAddress + 1) - 1;
  saveConfig();

  // Send page with new settings
  sendLEDPage();
} else if (strncmp("GET /ip?", (const char *)(Ethernet::buffer + pos), 8) == 0) {
  // Save settings
  config.iptype = (IPConfiguration)getIntArg((const char *)(Ethernet::buffer + pos + 7), "iptype", config.iptype);
  setIpArg((const char *)(Ethernet::buffer + pos + 7), "ip");
  saveConfig();

  // Send page with new settings
  sendIPPage();
  // Restart the chip to load the new configuration
  resetFunc();
}

} }

chrisstaite commented 10 years ago

I'll try to look at this later when I have more time. However, you simply need to consider the port parameter on the callback function and change the last parameter in the new ArtNet line to 2 from 1.

I'm releasing a new version soon that doesn't doesn't use new, instead has a configure method which is much more efficient.

folny commented 10 years ago

Thank you for your help I'm not such a good programmer I will have to wait for your help while I do not write an example of how to do it.

chrisstaite commented 10 years ago

If you pull the latest version things will likely be a little better but essentially you need to change your function as follows:

static void callback(unsigned short port, const char buffer, unsigned short length) { if (length < config.startAddress) return; length -= config.startAddress; buffer = buffer + config.startAddress; length = length / 3; if (length > config.connectedLEDs) length = config.connectedLEDs; if (port == 0) { for (int i = 0; i < length; ++i) { ledsPort1[i].r = buffer[i * 3]; ledsPort1[i].g = buffer[i * 3 + 1]; ledsPort1[i].b = buffer[i \ 3 + 2];

} } else if (port == 1) { for (int i = 0; i < length; ++i) { ledsPort2[i].r = buffer[i * 3]; ledsPort2[i].g = buffer[i * 3 + 1]; ledsPort2[i].b = buffer[i * 3 + 2];

} } FastSPI_LED.show(); }

folny commented 10 years ago

Thank you for the quick update code but something is still the problem of web configuration works properly but when I run a program for controlling the LED pixels and output A5 not at all do not know where could be the problem ?.

chrisstaite commented 10 years ago

Are you using the new version of FastLED? Try getting them to work using just the FastLED examples to start with, then add in the ArtNet code.

folny commented 10 years ago

Yes using the latest FastLed library, I think the problem is in the code Artnet when the previous version to work properly.