├── ArtGateOne_DMX └── ArtGateOne_DMX.ino ├── ArtGateOne_DMX_NO_OLED └── ArtGateOne_DMX_NO_OLED.ino ├── README.md └── libraries └── Dmx ├── examples ├── Dmx_Muxer │ └── Dmx_Muxer.pde ├── Dmx_Muxer_HTP │ └── Dmx_Muxer_HTP.pde ├── Dmx_Receive │ └── Dmx_Receive.pde ├── Dmx_Receive_chained │ └── Dmx_Receive_chained.pde ├── Dmx_Receive_chained_2048 │ └── Dmx_Receive_chained_2048.pde └── Dmx_Receive_interrupts │ └── Dmx_Receive_interrupts.pde ├── lib_dmx.cpp └── lib_dmx.h /ArtGateOne_DMX/ArtGateOne_DMX.ino: -------------------------------------------------------------------------------- 1 | /* 2 | ArtGateOne DMX v1.4.9 3 | */ 4 | 5 | #include // comment/uncomment #define USE_UARTx in lib_dmx.h as needed 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include "SSD1306Ascii.h" 11 | #include "SSD1306AsciiAvrI2c.h" 12 | #include 13 | 14 | #define DMX512 (0) // (250 kbaud - 2 to 512 channels) Standard USITT DMX-512 15 | #define analogPin A3 //Factory default 16 | #define I2C_ADDRESS 0x3C // OLED i2c addres 17 | 18 | SSD1306AsciiAvrI2c oled; 19 | 20 | bool invert = false; 21 | int post = 0; 22 | unsigned int datalen; 23 | int data; 24 | String strwww = String(); 25 | byte ArtPollReply[239]; 26 | 27 | // Get data from EEPROM 28 | byte intN = EEPROM.read(531); // NET 29 | byte intS = EEPROM.read(532); // Subnet 30 | byte intU = EEPROM.read(533); // Universe 31 | unsigned int intUniverse = ((intS * 16) + intU); 32 | 33 | byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; 34 | unsigned int localPort = 6454; // local port to listen on 35 | unsigned char packetBuffer[18]; // buffer to hold incoming packet, 36 | 37 | EthernetUDP Udp; 38 | EthernetServer server(80); 39 | 40 | void setup() { 41 | oled.begin(&Adafruit128x32, I2C_ADDRESS); 42 | oled.setFont(Arial14); 43 | oled.set1X(); 44 | oled.clear(); 45 | oled.println("ArtGateOne"); 46 | Ethernet.init(10); 47 | pinMode(analogPin, INPUT_PULLUP); 48 | int pinValue = digitalRead(analogPin); 49 | if (EEPROM.read(1023) == 0 || EEPROM.read(1023) == 255 || pinValue == LOW) // check first run or PIN3 to GND (FACTORY RESET) 50 | { // write default config 51 | EEPROM.update(512, 0); // DHCP 0=off, 1=on 52 | EEPROM.update(513, 2); // IP 53 | EEPROM.update(514, 0); 54 | EEPROM.update(515, 0); 55 | EEPROM.update(516, 10); 56 | EEPROM.update(517, 255); // SubNetMask 57 | EEPROM.update(518, 0); 58 | EEPROM.update(519, 0); 59 | EEPROM.update(520, 0); 60 | EEPROM.update(521, 0); // gateway 61 | EEPROM.update(522, 0); 62 | EEPROM.update(523, 0); 63 | EEPROM.update(524, 0); 64 | EEPROM.update(525, mac[0]); // mac adres 65 | EEPROM.update(526, mac[1]); // mac 66 | EEPROM.update(527, mac[2]); // mac 67 | EEPROM.update(528, mac[3]); // mac 68 | EEPROM.update(529, mac[4]); // mac 69 | EEPROM.update(530, mac[5]); // mac 70 | EEPROM.update(531, 0); // Art-Net Net 71 | EEPROM.update(532, 0); // Art-Net Sub 72 | EEPROM.update(533, 0); // Art-Net Uni 73 | EEPROM.update(534, 0); // boot scene 74 | EEPROM.update(1023, 1); // Factory default 75 | oled.println("RESET"); 76 | // delay(1500); 77 | } 78 | byte mac[] = { EEPROM.read(525), EEPROM.read(526), EEPROM.read(527), EEPROM.read(528), EEPROM.read(529), EEPROM.read(530) }; 79 | IPAddress ip(EEPROM.read(513), EEPROM.read(514), EEPROM.read(515), EEPROM.read(516)); 80 | IPAddress dns(0, 0, 0, 0); 81 | IPAddress subnet(EEPROM.read(517), EEPROM.read(518), EEPROM.read(519), EEPROM.read(520)); 82 | IPAddress gateway(EEPROM.read(521), EEPROM.read(522), EEPROM.read(523), EEPROM.read(524)); 83 | 84 | // initialize the ethernet device 85 | if (EEPROM.read(512) == 0) { 86 | Ethernet.begin(mac, ip, dns, gateway, subnet); 87 | } else { 88 | oled.println("DHCP..."); 89 | if (Ethernet.begin(mac) == 0) { 90 | Ethernet.begin(mac, ip, dns, gateway, subnet); 91 | } 92 | } 93 | delay(1500); 94 | 95 | Udp.begin(localPort); 96 | displaydata(); 97 | 98 | ArduinoDmx0.set_control_pin(2); // Arduino output pin for MAX485 input/output control (connect to MAX485-1 pins 2-3)(-1 not used)(2 control pin 2) 99 | ArduinoDmx0.set_tx_address(1); // set rx1 start address 100 | ArduinoDmx0.set_tx_channels(512); // 2 to 2048!! channels in DMX1000K (512 in standard mode) See lib_dmx.h *** new *** EXPERIMENTAL 101 | ArduinoDmx0.init_tx(DMX512); // starts universe 1 as tx, standard DMX 512 - See lib_dmx.h, now support for DMX faster modes (DMX 1000K) 102 | 103 | if (EEPROM.read(534) == 1) { 104 | for (int i = 0; i <= 511; i++) { 105 | ArduinoDmx0.TxBuffer[i] = EEPROM.read(i); 106 | } 107 | } 108 | makeArtPollReply(); 109 | } // end setup() 110 | 111 | void loop() { 112 | 113 | // listen for incoming clients 114 | EthernetClient client = server.available(); 115 | if (client) { 116 | // Serial.println("new client"); 117 | // an http request ends with a blank line 118 | boolean currentLineIsBlank = true; 119 | while (client.connected()) { 120 | if (client.available()) { 121 | char c = client.read(); 122 | strwww += c; 123 | // Serial.write(c); 124 | // if you've gotten to the end of the line (received a newline 125 | // character) and the line is blank, the http request has ended, 126 | // so you can send a reply 127 | if (c == '\n' && currentLineIsBlank) { 128 | // send a standard http response header 129 | if (strwww[0] == 71 && strwww[5] == 32) { 130 | client.println(F("HTTP/1.1 200 OK")); 131 | client.println(F("Content-Type: text/html, charset=utf-8")); 132 | client.println(F("Connection: close")); // the connection will be closed after completion of the response 133 | client.println(F("User-Agent: ArtGateOne")); 134 | client.println(); 135 | client.println(F("")); 136 | client.println(F("")); 137 | client.println(F("")); 138 | client.println(F("")); 139 | client.println(F("ArtGateOne setup")); 140 | client.println(F("")); 141 | client.println(F("")); 147 | client.println(F("")); 148 | client.println(F("")); 149 | client.println(F("
")); 150 | client.println(F("

ArtGateOne Setup

")); 151 | client.println(F("
")); 152 | client.println(F("
")); 153 | client.println(F("Ethernet:")); 154 | client.println(F("")); 155 | client.println(F("")); 166 | client.println(F("
")); 167 | client.println(F("")); 168 | client.print(F("")); 171 | client.println(F("
")); 172 | client.println(F("")); 173 | client.print(F("")); 176 | client.println(F("
")); 177 | client.println(F("")); 178 | client.print(F("")); 181 | client.println(F("
")); 182 | client.println(F("")); 183 | client.print(F("")); 216 | client.println(F("
")); 217 | client.println(F("
")); 218 | client.println(F("
")); 219 | client.println(F("
")); 220 | client.println(F("ArtNet:")); 221 | client.println(F("")); 222 | client.print(F("")); 225 | client.println(F("
")); 226 | client.println(F("")); 227 | client.print(F("")); 230 | client.println(F("
")); 231 | client.println(F("")); 232 | client.print(F("")); 235 | client.println(F("
")); 236 | client.println(F("
")); 237 | client.println(F("
")); 238 | client.println(F("
")); 239 | client.println(F("Boot:")); 240 | client.println(F("")); 241 | client.println(F("")); 252 | client.println(F("
")); 253 | client.println(F("
")); 254 | client.println(F("
")); 255 | client.println(F("")); 256 | client.println(F("")); 257 | client.println(F("
")); 258 | client.println(F("
")); 259 | client.println(F("
")); 260 | client.println(F("Art-Net™ Designed by and Copyright Artistic Licence Engineering Ltd")); 261 | client.println(F("
")); 262 | client.println(F("")); 263 | client.println(F("")); 264 | delay(10); 265 | strwww = String(); 266 | client.stop(); 267 | displaydata(); 268 | break; 269 | } 270 | if (strwww[0] == 71 && strwww[5] == 102) { // check favicon 271 | client.println("HTTP/1.1 200 OK"); 272 | client.println(); 273 | client.stop(); 274 | strwww = String(); 275 | break; 276 | } 277 | if (strwww[0] == 80) { // check POST frame 278 | datalen = 0; 279 | char *position = strstr(strwww.c_str(), "Content-Length"); 280 | if (position != NULL) { 281 | int startIndex = position - strwww.c_str() + 15; // Adjust the starting index based on the pattern 282 | char *endLine = strchr(position, '\n'); // Search for the end of the line 283 | if (endLine != NULL) { 284 | int endIndex = endLine - strwww.c_str(); 285 | char lengthValue[10]; // Assuming the length value is within 10 digits 286 | strncpy(lengthValue, strwww.c_str() + startIndex, endIndex - startIndex); 287 | lengthValue[endIndex - startIndex] = '\0'; 288 | datalen = atoi(lengthValue); 289 | } 290 | } 291 | post = 1; // ustawia odbior danych 292 | strwww = String(); 293 | client.println("HTTP/1.1 200 OK"); 294 | // client.println(); 295 | break; 296 | } 297 | } 298 | if (post == 1 && strwww.length() == datalen) { // recive data 299 | datadecode(); 300 | delay(1); 301 | // PRZETWARZA ODEBRANE DANE I WYŚWIETLA STRONE KONCOWA 302 | client.println(F("HTTP/1.1 200 OK")); 303 | client.println(F("Content-Type: text/html, charset=utf-8")); 304 | client.println(F("Connection: close")); // the connection will be closed after completion of the response 305 | client.println(F("User-Agent: ArtGateOne")); 306 | client.println(); 307 | client.println(F("")); 308 | client.println(F("")); 309 | client.println(F("")); 310 | client.println(F("")); //szara 311 | client.println(F("ArtGateOne setup")); 312 | client.println(F("")); 313 | client.print(F("")); 322 | client.println(F("")); 323 | client.println(F("")); 329 | client.println(F("")); 330 | client.println(F("")); 331 | client.println(F("
")); 332 | client.println(F("

ArtGateOne

")); 333 | client.println(F("

Save configuration ...

")); 334 | client.println(F("
")); 335 | client.println(F("")); 336 | client.println(F("")); 337 | client.println(F("")); 338 | delay(1); 339 | client.stop(); 340 | strwww = String(); 341 | post = 0; 342 | if (EEPROM.read(512) == 1) { 343 | //oled.clear(); 344 | //oled.println(" ArtGateOne"); 345 | oled.println("DHCP..."); 346 | Ethernet.begin(mac); 347 | Ethernet.maintain(); 348 | } else { 349 | IPAddress newIp(EEPROM.read(513), EEPROM.read(514), EEPROM.read(515), EEPROM.read(516)); 350 | Ethernet.setLocalIP(newIp); 351 | IPAddress newSubnet(EEPROM.read(517), EEPROM.read(518), EEPROM.read(519), EEPROM.read(520)); 352 | Ethernet.setSubnetMask(newSubnet); 353 | IPAddress newGateway(EEPROM.read(521), EEPROM.read(522), EEPROM.read(523), EEPROM.read(524)); 354 | Ethernet.setGatewayIP(newGateway); 355 | } 356 | IPAddress localIP = Ethernet.localIP(); 357 | delay(500); 358 | displaydata(); 359 | makeArtPollReply(); 360 | break; 361 | } 362 | if (c == '\n') { 363 | // you're starting a new line 364 | currentLineIsBlank = true; 365 | } else if (c != '\r') { 366 | // you've gotten a character on the current line 367 | currentLineIsBlank = false; 368 | } 369 | } 370 | } 371 | // give the web browser time to receive the data 372 | // delay(1); 373 | // close the connection: 374 | // client.stop(); 375 | // Serial.println("client disconnected"); 376 | // Serial.print(strwww[0]); 377 | // strwww = String(); 378 | } 379 | 380 | // if there's udp data available, read a packet 381 | int packetSize = Udp.parsePacket(); 382 | if (packetSize == 14 || packetSize == 18) { //ArtPoll 383 | invert = !invert; 384 | oled.invertDisplay(invert); 385 | //incrementCounter();//<-- need more memory - use on mega 386 | // send a ArtPollReply to the IP address and port that sent us the packet we received 387 | Udp.beginPacket(Udp.remoteIP(), Udp.remotePort()); 388 | Udp.write(ArtPollReply, 239); 389 | Udp.endPacket(); 390 | } else if (packetSize == 530) { //ArtDMX 391 | 392 | // read the packet into packetBuffer 393 | Udp.read(packetBuffer, 18); 394 | 395 | if (packetBuffer[15] == intN && packetBuffer[14] == intUniverse) { // check artnet net & universe (sub/uni) 396 | for (int i = 0; i <= 511; i++) { 397 | Udp.read(packetBuffer, 1); 398 | ArduinoDmx0.TxBuffer[i] = packetBuffer[0]; 399 | } 400 | } 401 | } 402 | } // end loop() 403 | 404 | void makeArtPollReply() { //Art-Net 4 Protocol Release V1.4dh 19/7/2023 405 | ArtPollReply[0] = byte('A'); // A 406 | ArtPollReply[1] = byte('r'); // r 407 | ArtPollReply[2] = byte('t'); // t 408 | ArtPollReply[3] = byte('-'); // - 409 | ArtPollReply[4] = byte('N'); // N 410 | ArtPollReply[5] = byte('e'); // e 411 | ArtPollReply[6] = byte('t'); // t 412 | //ArtPollReply[7] = 0x00; // 0x00 413 | 414 | //ArtPollReply[8] = 0x00; // OpCode[0] 415 | ArtPollReply[9] = 0x21; // OpCode[1] 416 | 417 | ArtPollReply[10] = Ethernet.localIP()[0]; // IPV4 [0] 418 | ArtPollReply[11] = Ethernet.localIP()[1]; // IPV4 [1] 419 | ArtPollReply[12] = Ethernet.localIP()[2]; // IPV4 [2] 420 | ArtPollReply[13] = Ethernet.localIP()[3]; // IPV4 [3] 421 | 422 | ArtPollReply[14] = 0x36; // IP Port Low 423 | ArtPollReply[15] = 0x19; // IP Port Hi 424 | 425 | ArtPollReply[16] = 0x01; // High byte of Version 426 | ArtPollReply[17] = 0x04; // Low byte of Version 427 | 428 | ArtPollReply[18] = intN; // NetSwitch 429 | ArtPollReply[19] = intS; // Net Sub Switch 430 | 431 | ArtPollReply[20] = 0xFF; // OEMHi 432 | ArtPollReply[21] = 0xFF; // OEMLow 433 | 434 | //ArtPollReply[22] = 0x00; // Ubea Version 435 | 436 | ArtPollReply[23] = 0xE0; // Status1 437 | 438 | //ArtPollReply[24] = 0x00; // ESTA LO 439 | //ArtPollReply[25] = 0x00; // ESTA HI 440 | 441 | ArtPollReply[26] = byte('A'); // A //Short Name [18] 442 | ArtPollReply[27] = byte('r'); 443 | ArtPollReply[28] = byte('t'); 444 | ArtPollReply[29] = byte('G'); 445 | ArtPollReply[30] = byte('a'); 446 | ArtPollReply[31] = byte('t'); 447 | ArtPollReply[32] = byte('e'); 448 | ArtPollReply[33] = byte('O'); 449 | ArtPollReply[34] = byte('n'); 450 | ArtPollReply[35] = byte('e'); 451 | 452 | ArtPollReply[44] = byte('A'); //Long Name [64] 453 | ArtPollReply[45] = byte('r'); 454 | ArtPollReply[46] = byte('t'); 455 | ArtPollReply[47] = byte('G'); 456 | ArtPollReply[48] = byte('a'); 457 | ArtPollReply[49] = byte('t'); 458 | ArtPollReply[50] = byte('e'); 459 | ArtPollReply[51] = byte('O'); 460 | ArtPollReply[52] = byte('n'); 461 | ArtPollReply[53] = byte('e'); 462 | ArtPollReply[54] = byte(' '); 463 | ArtPollReply[55] = byte('D'); 464 | ArtPollReply[56] = byte('M'); 465 | ArtPollReply[57] = byte('X'); 466 | ArtPollReply[58] = byte(' '); 467 | ArtPollReply[59] = byte('1'); 468 | ArtPollReply[60] = byte('.'); 469 | ArtPollReply[61] = byte('4'); 470 | 471 | ArtPollReply[108] = byte('#'); // NodeReport 472 | ArtPollReply[109] = byte('0'); 473 | ArtPollReply[110] = byte('0'); 474 | ArtPollReply[111] = byte('0'); 475 | ArtPollReply[112] = byte('1'); 476 | ArtPollReply[113] = byte(' '); 477 | ArtPollReply[114] = byte('['); 478 | ArtPollReply[115] = byte('0'); 479 | ArtPollReply[116] = byte('0'); 480 | ArtPollReply[117] = byte('0'); 481 | ArtPollReply[118] = byte('0'); 482 | ArtPollReply[119] = byte(']'); 483 | ArtPollReply[120] = byte(' '); 484 | ArtPollReply[121] = byte('A'); 485 | ArtPollReply[122] = byte('r'); 486 | ArtPollReply[123] = byte('t'); 487 | ArtPollReply[124] = byte('G'); 488 | ArtPollReply[125] = byte('a'); 489 | ArtPollReply[126] = byte('t'); 490 | ArtPollReply[127] = byte('e'); 491 | ArtPollReply[128] = byte('O'); 492 | ArtPollReply[129] = byte('n'); 493 | ArtPollReply[130] = byte('e'); 494 | ArtPollReply[131] = byte(' '); 495 | ArtPollReply[132] = byte('A'); 496 | ArtPollReply[133] = byte('r'); 497 | ArtPollReply[134] = byte('t'); 498 | ArtPollReply[135] = byte('-'); 499 | ArtPollReply[136] = byte('N'); 500 | ArtPollReply[137] = byte('e'); 501 | ArtPollReply[138] = byte('t'); 502 | ArtPollReply[139] = byte(' '); 503 | ArtPollReply[140] = byte('P'); 504 | ArtPollReply[141] = byte('r'); 505 | ArtPollReply[142] = byte('o'); 506 | ArtPollReply[143] = byte('d'); 507 | ArtPollReply[144] = byte('u'); 508 | ArtPollReply[145] = byte('c'); 509 | ArtPollReply[146] = byte('t'); 510 | ArtPollReply[147] = byte('.'); 511 | ArtPollReply[148] = byte(' '); 512 | ArtPollReply[149] = byte('G'); 513 | ArtPollReply[150] = byte('o'); 514 | ArtPollReply[151] = byte('o'); 515 | ArtPollReply[152] = byte('d'); 516 | ArtPollReply[153] = byte(' '); 517 | ArtPollReply[154] = byte('B'); 518 | ArtPollReply[155] = byte('o'); 519 | ArtPollReply[156] = byte('o'); 520 | ArtPollReply[157] = byte('t'); 521 | ArtPollReply[158] = byte('.'); 522 | 523 | 524 | //ArtPollReply[172] = 0x00; // NumPorts Hi 525 | ArtPollReply[173] = 0x01; // NumPorts Lo 526 | 527 | ArtPollReply[174] = 0x80; // Port Types [0] 528 | //ArtPollReply[175] = 0x00; // Port Types [1] 529 | //ArtPollReply[176] = 0x00; // Port Types [2] 530 | //ArtPollReply[177] = 0x00; // Port Types [3] 531 | 532 | ArtPollReply[178] = 0x08; // GoodInput [0] 533 | //ArtPollReply[179] = 0x00; // GoodInput [1] 534 | //ArtPollReply[180] = 0x00; // GoodInput [2] 535 | //ArtPollReply[181] = 0x00; // GoodInput [3] 536 | 537 | ArtPollReply[182] = 0x80; // GoodOutputA [0] 538 | //ArtPollReply[183] = 0x00; // GoodOutputA [1] 539 | //ArtPollReply[184] = 0x00; // GoodOutputA [2] 540 | //ArtPollReply[185] = 0x00; // GoodOutputA [3] 541 | 542 | //ArtPollReply[186] = 0x00; // SwIn [0] 543 | //ArtPollReply[187] = 0x00; // SwIn [1] 544 | //ArtPollReply[188] = 0x00; // SwIn [2] 545 | //ArtPollReply[189] = 0x00; // SwIn [3] 546 | 547 | ArtPollReply[190] = intU; // SwOut [0] 548 | //ArtPollReply[191] = 0x00; // SwOut [1] 549 | //ArtPollReply[192] = 0x00; // SwOut [2] 550 | //ArtPollReply[193] = 0x00; // SwOut [3] 551 | 552 | //ArtPollReply[194] = 0x00; // AcnPriority 553 | 554 | //ArtPollReply[195] = 0x00; // SwMacro 555 | 556 | //ArtPollReply[196] = 0x00; // SwRemote 557 | 558 | //ArtPollReply[197] = 0x00; // Spare 559 | //ArtPollReply[198] = 0x00; // Spare 560 | //ArtPollReply[199] = 0x00; // Spare 561 | 562 | //ArtPollReply[200] = 0x00; // Style 563 | 564 | ArtPollReply[201] = mac[0]; // MAC HI 565 | ArtPollReply[202] = mac[1]; // MAC 566 | ArtPollReply[203] = mac[2]; // MAC 567 | ArtPollReply[204] = mac[3]; // MAC 568 | ArtPollReply[205] = mac[4]; // MAC 569 | ArtPollReply[206] = mac[5]; // MAC LO 570 | 571 | //ArtPollReply[207] = 0x00; // BIND IP 0 572 | //ArtPollReply[208] = 0x00; // BIND IP 1 573 | //ArtPollReply[209] = 0x00; // BIND IP 2 574 | //ArtPollReply[210] = 0x00; // BIND IP 3 575 | //ArtPollReply[211] = 0x00; // BInd Index 576 | 577 | ArtPollReply[212] = 0x0D; // Status2 578 | if (EEPROM.read(512) == 1) { 579 | ArtPollReply[212] = 0x0F; // DHCP USED 580 | } 581 | 582 | //ArtPollReply[213] = 0x00; // GoodOutputB [0] 583 | //ArtPollReply[214] = 0x00; // GoodOutputB [1] 584 | //ArtPollReply[215] = 0x00; // GoodOutputB [2] 585 | //ArtPollReply[216] = 0x00; // GoodOutputB [3] 586 | 587 | ArtPollReply[217] = 0x20; // Status3 588 | 589 | //ArtPollReply[218] = 0x00; // DefaulRespUID Hi 590 | //ArtPollReply[219] = 0x00; // DefaulRespUID 591 | //ArtPollReply[220] = 0x00; // DefaulRespUID 592 | //ArtPollReply[221] = 0x00; // DefaulRespUID 593 | //ArtPollReply[222] = 0x00; // DefaulRespUID 594 | //ArtPollReply[223] = 0x00; // DefaulRespUID Lo 595 | 596 | //ArtPollReply[224] = 0x00; // UserHi 597 | //ArtPollReply[225] = 0x00; // UserLo 598 | 599 | //ArtPollReply[226] = 0x00; // RefreshRateHi 600 | //ArtPollReply[227] = 0x00; // RefreshRateLo 601 | 602 | //Filler 11 x 8 Transmit as zero. For future expansion. 603 | 604 | return; 605 | } // end makeArtPollReply() 606 | 607 | void datadecode() { 608 | int j = 0; 609 | for (unsigned int i = 0; i <= datalen; i++) { 610 | if (strwww[i] == 61) { // if find "=" 611 | j++; 612 | i++; 613 | if (j == 1) { // DHCP 614 | EEPROM.update(512, (strwww[i] - 48)); 615 | } 616 | if (j == 2) { // IP ADDRES 617 | data = dataadd(i); 618 | EEPROM.update(513, data); 619 | i = i + 2; 620 | if (data >= 10) { 621 | i++; 622 | } 623 | if (data >= 100) { 624 | i++; 625 | } 626 | data = dataadd(i); 627 | EEPROM.update(514, data); 628 | i = i + 2; 629 | if (data >= 10) { 630 | i++; 631 | } 632 | if (data >= 100) { 633 | i++; 634 | } 635 | data = dataadd(i); 636 | EEPROM.update(515, data); 637 | i = i + 2; 638 | if (data >= 10) { 639 | i++; 640 | } 641 | if (data >= 100) { 642 | i++; 643 | } 644 | data = dataadd(i); 645 | EEPROM.update(516, data); 646 | } 647 | if (j == 3) { // SUBNET 648 | data = dataadd(i); 649 | EEPROM.update(517, data); 650 | i = i + 2; 651 | if (data >= 10) { 652 | i++; 653 | } 654 | if (data >= 100) { 655 | i++; 656 | } 657 | data = dataadd(i); 658 | EEPROM.update(518, data); 659 | i = i + 2; 660 | if (data >= 10) { 661 | i++; 662 | } 663 | if (data >= 100) { 664 | i++; 665 | } 666 | data = dataadd(i); 667 | EEPROM.update(519, data); 668 | i = i + 2; 669 | if (data >= 10) { 670 | i++; 671 | } 672 | if (data >= 100) { 673 | i++; 674 | } 675 | data = dataadd(i); 676 | EEPROM.update(520, data); 677 | } 678 | if (j == 4) { // GATEWAY 679 | data = dataadd(i); 680 | EEPROM.update(521, data); 681 | i = i + 2; 682 | if (data >= 10) { 683 | i++; 684 | } 685 | if (data >= 100) { 686 | i++; 687 | } 688 | data = dataadd(i); 689 | EEPROM.update(522, data); 690 | i = i + 2; 691 | if (data >= 10) { 692 | i++; 693 | } 694 | if (data >= 100) { 695 | i++; 696 | } 697 | data = dataadd(i); 698 | EEPROM.update(523, data); 699 | i = i + 2; 700 | if (data >= 10) { 701 | i++; 702 | } 703 | if (data >= 100) { 704 | i++; 705 | } 706 | data = dataadd(i); 707 | EEPROM.update(524, data); 708 | } 709 | if (j == 5) { // MAC 710 | EEPROM.update(525, datamac(i)); 711 | i = i + 5; 712 | EEPROM.update(526, datamac(i)); 713 | i = i + 5; 714 | EEPROM.update(527, datamac(i)); 715 | i = i + 5; 716 | EEPROM.update(528, datamac(i)); 717 | i = i + 5; 718 | EEPROM.update(529, datamac(i)); 719 | i = i + 5; 720 | EEPROM.update(530, datamac(i)); 721 | } 722 | if (j == 6) { // NET 723 | data = dataadd(i); 724 | EEPROM.update(531, data); 725 | intN = data; // NET 726 | } 727 | if (j == 7) { // SUBNET 728 | data = dataadd(i); 729 | EEPROM.update(532, data); 730 | intS = data; 731 | } 732 | if (j == 8) { // UNIVERSE 733 | data = dataadd(i); 734 | EEPROM.update(533, data); 735 | intU = data; 736 | intUniverse = ((intS * 16) + intU); 737 | } 738 | if (j == 9) { // SCENE 739 | int data = (strwww[i] - 48); 740 | if (data <= 1) { 741 | EEPROM.update(534, data); 742 | } else { 743 | EEPROM.update(534, 1); //New Boot Scene 744 | // save to eeprom 745 | for (i = 0; i <= 511; i++) { 746 | EEPROM.update(i, ArduinoDmx0.TxBuffer[i]); 747 | } 748 | } 749 | } 750 | } 751 | } 752 | } // end datadecode() 753 | 754 | int dataadd(int i) { 755 | data = 0; 756 | while (strwww[i] != 38 && strwww[i] != 46) { 757 | data = ((data * 10) + (strwww[i] - 48)); 758 | i++; 759 | } 760 | return data; 761 | } // end dataadd() 762 | 763 | int datamac(int i) { 764 | data = strwww[i]; 765 | if (data <= 57) { 766 | data = data - 48; 767 | } else if (data >= 65) { 768 | data = data - 55; 769 | } 770 | 771 | data = data * 16; 772 | 773 | if (strwww[i + 1] <= 57) { 774 | data = data + (strwww[i + 1] - 48); 775 | } else if (strwww[i + 1] >= 65) { 776 | data = data + (strwww[i + 1] - 55); 777 | } 778 | return data; 779 | } // end datamac() 780 | 781 | void displaydata() { //Display oled data 782 | 783 | oled.clear(); 784 | oled.print(" IP : "); 785 | oled.println(Ethernet.localIP()); 786 | 787 | /* 788 | oled.print(" Mask: "); 789 | oled.println(Ethernet.subnetMask()); 790 | 791 | oled.print(" Net "); 792 | oled.print(intN, HEX); 793 | oled.print(" Sub "); 794 | oled.print(intS, HEX); 795 | oled.print(" Uni "); 796 | oled.println(intU, HEX); 797 | */ 798 | 799 | oled.print(" Universe "); 800 | oled.print((intUniverse + (intN * 256))); 801 | 802 | if (EEPROM.read(534) == 1) { 803 | oled.println(" BS"); 804 | } else { 805 | oled.println(); 806 | } 807 | return; 808 | } // end displaydata() 809 | 810 | /* 811 | void incrementCounter() { 812 | static int counter = 0; // Static variable to retain the value between function calls 813 | counter++; // Increment the counter 814 | 815 | if (counter > 9999) { 816 | counter = 0; // Reset the counter to 0 after reaching 9999 817 | } 818 | 819 | // Convert the number to a character array (string) 820 | char buffer[5]; // Array to store the result 821 | snprintf(buffer, sizeof(buffer), "%04d", counter); // The format "%04d" ensures leading zeros in the number 822 | 823 | // Write the digits as characters to the ArtPollReply variables 824 | ArtPollReply[115] = buffer[0]; 825 | ArtPollReply[116] = buffer[1]; 826 | ArtPollReply[117] = buffer[2]; 827 | ArtPollReply[118] = buffer[3]; 828 | } // end incrementCounter() 829 | */ 830 | -------------------------------------------------------------------------------- /ArtGateOne_DMX_NO_OLED/ArtGateOne_DMX_NO_OLED.ino: -------------------------------------------------------------------------------- 1 | /* 2 | ArtGateOne DMX v1.4.6 3 | */ 4 | 5 | #include // comment/uncomment #define USE_UARTx in lib_dmx.h as needed 6 | #include 7 | #include 8 | //#include 9 | //#include 10 | //#include "SSD1306Ascii.h" 11 | //#include "SSD1306AsciiAvrI2c.h" 12 | #include 13 | 14 | #define DMX512 (0) // (250 kbaud - 2 to 512 channels) Standard USITT DMX-512 15 | #define analogPin A3 //Factory default 16 | //#define I2C_ADDRESS 0x3C // OLED i2c addres - 0x3C 128x32, 0x3D 128x64 17 | 18 | //SSD1306AsciiAvrI2c oled; 19 | 20 | bool invert = false; 21 | int post = 0; 22 | unsigned int datalen; 23 | int data; 24 | String strwww = String(); 25 | byte ArtPollReply[239]; 26 | 27 | // Get data from EEPROM 28 | byte intN = EEPROM.read(531); // NET 29 | byte intS = EEPROM.read(532); // Subnet 30 | byte intU = EEPROM.read(533); // Universe 31 | unsigned int intUniverse = ((intS * 16) + intU); 32 | 33 | byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; 34 | unsigned int localPort = 6454; // local port to listen on 35 | unsigned char packetBuffer[18]; // buffer to hold incoming packet, 36 | 37 | EthernetUDP Udp; 38 | EthernetServer server(80); 39 | 40 | void setup() { 41 | //oled.begin(&Adafruit128x32, I2C_ADDRESS); 42 | //oled.setFont(Arial14); 43 | //oled.set1X(); 44 | //oled.clear(); 45 | //oled.println(" ArtGateOne"); 46 | Ethernet.init(10); 47 | pinMode(analogPin, INPUT_PULLUP); 48 | int pinValue = digitalRead(analogPin); 49 | if (EEPROM.read(1023) == 0 || EEPROM.read(1023) == 255 || pinValue == LOW) // check first run or PIN3 to GND (FACTORY RESET) 50 | { // write default config 51 | EEPROM.update(512, 0); // DHCP 0=off, 1=on 52 | EEPROM.update(513, 2); // IP 53 | EEPROM.update(514, 0); 54 | EEPROM.update(515, 0); 55 | EEPROM.update(516, 10); 56 | EEPROM.update(517, 255); // SubNetMask 57 | EEPROM.update(518, 0); 58 | EEPROM.update(519, 0); 59 | EEPROM.update(520, 0); 60 | EEPROM.update(521, 0); // gateway 61 | EEPROM.update(522, 0); 62 | EEPROM.update(523, 0); 63 | EEPROM.update(524, 0); 64 | EEPROM.update(525, mac[0]); // mac adres 65 | EEPROM.update(526, mac[1]); // mac 66 | EEPROM.update(527, mac[2]); // mac 67 | EEPROM.update(528, mac[3]); // mac 68 | EEPROM.update(529, mac[4]); // mac 69 | EEPROM.update(530, mac[5]); // mac 70 | EEPROM.update(531, 0); // Art-Net Net 71 | EEPROM.update(532, 0); // Art-Net Sub 72 | EEPROM.update(533, 0); // Art-Net Uni 73 | EEPROM.update(534, 0); // boot scene 74 | EEPROM.update(1023, 1); // Factory default 75 | //oled.println(" RESET"); 76 | // delay(1500); 77 | } 78 | byte mac[] = { EEPROM.read(525), EEPROM.read(526), EEPROM.read(527), EEPROM.read(528), EEPROM.read(529), EEPROM.read(530) }; 79 | IPAddress ip(EEPROM.read(513), EEPROM.read(514), EEPROM.read(515), EEPROM.read(516)); 80 | IPAddress dns(0, 0, 0, 0); 81 | IPAddress subnet(EEPROM.read(517), EEPROM.read(518), EEPROM.read(519), EEPROM.read(520)); 82 | IPAddress gateway(EEPROM.read(521), EEPROM.read(522), EEPROM.read(523), EEPROM.read(524)); 83 | 84 | // initialize the ethernet device 85 | if (EEPROM.read(512) == 0) { 86 | Ethernet.begin(mac, ip, dns, gateway, subnet); 87 | } else { 88 | //oled.println(" DHCP ..."); 89 | if (Ethernet.begin(mac) == 0) { 90 | Ethernet.begin(mac, ip, dns, gateway, subnet); 91 | } 92 | } 93 | // delay(1500); 94 | 95 | Udp.begin(localPort); 96 | displaydata(); 97 | 98 | ArduinoDmx0.set_control_pin(2); // Arduino output pin for MAX485 input/output control (connect to MAX485-1 pins 2-3)(-1 not used)(2 control pin 2) 99 | ArduinoDmx0.set_tx_address(1); // set rx1 start address 100 | ArduinoDmx0.set_tx_channels(512); // 2 to 2048!! channels in DMX1000K (512 in standard mode) See lib_dmx.h *** new *** EXPERIMENTAL 101 | ArduinoDmx0.init_tx(DMX512); // starts universe 1 as tx, standard DMX 512 - See lib_dmx.h, now support for DMX faster modes (DMX 1000K) 102 | 103 | if (EEPROM.read(534) == 1) { 104 | for (int i = 0; i <= 511; i++) { 105 | ArduinoDmx0.TxBuffer[i] = EEPROM.read(i); 106 | } 107 | } 108 | makeArtPollReply(); 109 | } // end setup() 110 | 111 | void loop() { 112 | 113 | // listen for incoming clients 114 | EthernetClient client = server.available(); 115 | if (client) { 116 | // Serial.println("new client"); 117 | // an http request ends with a blank line 118 | boolean currentLineIsBlank = true; 119 | while (client.connected()) { 120 | if (client.available()) { 121 | char c = client.read(); 122 | strwww += c; 123 | // Serial.write(c); 124 | // if you've gotten to the end of the line (received a newline 125 | // character) and the line is blank, the http request has ended, 126 | // so you can send a reply 127 | if (c == '\n' && currentLineIsBlank) { 128 | // send a standard http response header 129 | if (strwww[0] == 71 && strwww[5] == 32) { 130 | client.println(F("HTTP/1.1 200 OK")); 131 | client.println(F("Content-Type: text/html, charset=utf-8")); 132 | client.println(F("Connection: close")); // the connection will be closed after completion of the response 133 | client.println(F("User-Agent: ArtGateOne")); 134 | client.println(); 135 | client.println(F("")); 136 | client.println(F("")); 137 | client.println(F("")); 138 | client.println(F("")); 139 | client.println(F("ArtGateOne setup")); 140 | client.println(F("")); 141 | client.println(F("")); 142 | client.println(F("")); 143 | client.println(F("")); 144 | client.println(F("")); 145 | client.println(F("")); 151 | client.println(F("")); 152 | client.println(F("")); 153 | client.println(F("
")); 154 | client.println(F("

ArtGateOne Setup

")); 155 | client.println(F("
")); 156 | client.println(F("
")); 157 | client.println(F("Ethernet:")); 158 | client.println(F("")); 159 | client.println(F("
")); 168 | 169 | client.println(F("")); 170 | client.print(F("
")); 173 | client.println(F("")); 174 | client.print(F("
")); 177 | client.println(F("")); 178 | client.print(F("
")); 181 | client.println(F("")); 182 | client.print(F("
")); 213 | client.println(F("

")); 214 | client.println(F("
")); 215 | client.println(F("ArtNet:")); 216 | client.println(F("")); 217 | client.print(F("
")); 220 | client.println(F("")); 221 | client.print(F("
")); 224 | client.println(F("")); 225 | client.print(F("
")); 228 | client.println(F("

")); 229 | client.println(F("
")); 230 | client.println(F("Boot:")); 231 | client.println(F("")); 232 | client.println(F("
")); 242 | client.println(F("

")); 243 | client.println(F("")); 244 | client.println(F("


")); 245 | client.println(F("
")); 246 | client.println(F("

\" Art - Net™ Designed by and Copyright Artistic Licence Engineering Ltd \"

")); 247 | client.println(F("
")); 248 | client.println(F("")); 249 | client.println(F("")); 250 | delay(10); 251 | strwww = String(); 252 | client.stop(); 253 | displaydata(); 254 | break; 255 | } 256 | if (strwww[0] == 71 && strwww[5] == 102) { // check favicon 257 | client.println("HTTP/1.1 200 OK"); 258 | client.println(); 259 | client.stop(); 260 | strwww = String(); 261 | break; 262 | } 263 | if (strwww[0] == 80) { // check POST frame 264 | datalen = 0; 265 | char *position = strstr(strwww.c_str(), "Content-Length"); 266 | if (position != NULL) { 267 | int startIndex = position - strwww.c_str() + 15; // Adjust the starting index based on the pattern 268 | char *endLine = strchr(position, '\n'); // Search for the end of the line 269 | if (endLine != NULL) { 270 | int endIndex = endLine - strwww.c_str(); 271 | char lengthValue[10]; // Assuming the length value is within 10 digits 272 | strncpy(lengthValue, strwww.c_str() + startIndex, endIndex - startIndex); 273 | lengthValue[endIndex - startIndex] = '\0'; 274 | datalen = atoi(lengthValue); 275 | } 276 | } 277 | post = 1; // ustawia odbior danych 278 | strwww = String(); 279 | client.println("HTTP/1.1 200 OK"); 280 | // client.println(); 281 | break; 282 | } 283 | } 284 | if (post == 1 && strwww.length() == datalen) { // odbior danych 285 | datadecode(); 286 | delay(1); 287 | // PRZETWARZA ODEBRANE DANE I WYŚWIETLA STRONE KONCOWA 288 | client.println(F("HTTP/1.1 200 OK")); 289 | client.println(F("Content-Type: text/html, charset=utf-8")); 290 | client.println(F("Connection: close")); // the connection will be closed after completion of the response 291 | client.println(F("User-Agent: ArtGateOne")); 292 | client.println(); 293 | client.println(F("")); 294 | client.println(F("")); 295 | client.println(F("")); 296 | client.println(F(""));//szara 297 | client.println(F("ArtGateOne setup")); 298 | client.println(F("")); 299 | client.print(F("")); 308 | client.println(F("")); 309 | client.println(F("")); 310 | client.println(F("")); 311 | client.println(F("")); 312 | client.println(F("")); 318 | client.println(F("")); 319 | client.println(F("")); 320 | client.println(F("
")); 321 | client.println(F("

ArtGateOne

")); 322 | client.println(F("

Save configuration ...

")); 323 | client.println(F("
")); 324 | client.println(F("")); 325 | client.println(F("")); 326 | client.println(F("")); 327 | delay(1); 328 | client.stop(); 329 | strwww = String(); 330 | post = 0; 331 | if (EEPROM.read(512) == 1) { 332 | //oled.clear(); 333 | //oled.println(" ArtGateOne"); 334 | //oled.println(" DHCP ..."); 335 | Ethernet.begin(mac); 336 | Ethernet.maintain(); 337 | } else { 338 | IPAddress newIp(EEPROM.read(513), EEPROM.read(514), EEPROM.read(515), EEPROM.read(516)); 339 | Ethernet.setLocalIP(newIp); 340 | IPAddress newSubnet(EEPROM.read(517), EEPROM.read(518), EEPROM.read(519), EEPROM.read(520)); 341 | Ethernet.setSubnetMask(newSubnet); 342 | IPAddress newGateway(EEPROM.read(521), EEPROM.read(522), EEPROM.read(523), EEPROM.read(524)); 343 | Ethernet.setGatewayIP(newGateway); 344 | } 345 | IPAddress localIP = Ethernet.localIP(); 346 | delay(500); 347 | displaydata(); 348 | makeArtPollReply(); 349 | break; 350 | } 351 | if (c == '\n') { 352 | // you're starting a new line 353 | currentLineIsBlank = true; 354 | } else if (c != '\r') { 355 | // you've gotten a character on the current line 356 | currentLineIsBlank = false; 357 | } 358 | } 359 | } 360 | // give the web browser time to receive the data 361 | // delay(1); 362 | // close the connection: 363 | // client.stop(); 364 | // Serial.println("client disconnected"); 365 | // Serial.print(strwww[0]); 366 | // strwww = String(); 367 | } 368 | 369 | // if there's data available, read a packet 370 | int packetSize = Udp.parsePacket(); 371 | if (packetSize == 14 || packetSize == 18) { 372 | invert = !invert; 373 | //oled.invertDisplay(invert); 374 | incrementCounter(); 375 | // send a ArtPollReply to the IP address and port that sent us the packet we received 376 | Udp.beginPacket(Udp.remoteIP(), Udp.remotePort()); 377 | Udp.write(ArtPollReply, 239); 378 | Udp.endPacket(); 379 | } else if (packetSize == 530) { 380 | 381 | // read the packet into packetBuffer 382 | Udp.read(packetBuffer, 18); 383 | 384 | if (packetBuffer[15] == intN && packetBuffer[14] == intUniverse) { // check artnet net & universe (sub/uni) 385 | for (int i = 0; i <= 511; i++) { 386 | Udp.read(packetBuffer, 1); 387 | ArduinoDmx0.TxBuffer[i] = packetBuffer[0]; 388 | } 389 | } 390 | } 391 | } // end loop() 392 | 393 | void makeArtPollReply() { //Art-Net 4 Protocol Release V1.4dh 19/7/2023 394 | ArtPollReply[0] = byte('A'); // A 395 | ArtPollReply[1] = byte('r'); // r 396 | ArtPollReply[2] = byte('t'); // t 397 | ArtPollReply[3] = byte('-'); // - 398 | ArtPollReply[4] = byte('N'); // N 399 | ArtPollReply[5] = byte('e'); // e 400 | ArtPollReply[6] = byte('t'); // t 401 | ArtPollReply[7] = 0x00; // 0x00 402 | 403 | ArtPollReply[8] = 0x00; // OpCode[0] 404 | ArtPollReply[9] = 0x21; // OpCode[1] 405 | 406 | ArtPollReply[10] = Ethernet.localIP()[0]; // IPV4 [0] 407 | ArtPollReply[11] = Ethernet.localIP()[1]; // IPV4 [1] 408 | ArtPollReply[12] = Ethernet.localIP()[2]; // IPV4 [2] 409 | ArtPollReply[13] = Ethernet.localIP()[3]; // IPV4 [3] 410 | 411 | ArtPollReply[14] = 0x36; // IP Port Low 412 | ArtPollReply[15] = 0x19; // IP Port Hi 413 | 414 | ArtPollReply[16] = 0x01; // High byte of Version 415 | ArtPollReply[17] = 0x04; // Low byte of Version 416 | 417 | ArtPollReply[18] = intN; // NetSwitch 418 | ArtPollReply[19] = intS; // Net Sub Switch 419 | 420 | ArtPollReply[20] = 0xFF; // OEMHi 421 | ArtPollReply[21] = 0xFF; // OEMLow 422 | 423 | ArtPollReply[22] = 0x00; // Ubea Version 424 | 425 | ArtPollReply[23] = 0xE0; // Status1 426 | 427 | ArtPollReply[24] = 0x00; // ESTA LO 428 | ArtPollReply[25] = 0x00; // ESTA HI 429 | 430 | ArtPollReply[26] = byte('A'); // A //Short Name [18] 431 | ArtPollReply[27] = byte('r'); // r 432 | ArtPollReply[28] = byte('t'); // t 433 | ArtPollReply[29] = byte('G'); // G 434 | ArtPollReply[30] = byte('a'); // a 435 | ArtPollReply[31] = byte('t'); // t 436 | ArtPollReply[32] = byte('e'); // e 437 | ArtPollReply[33] = byte('O'); // O 438 | ArtPollReply[34] = byte('n'); // n 439 | ArtPollReply[35] = byte('e'); // e 440 | 441 | ArtPollReply[44] = byte('A'); // A //Long Name [64] 442 | ArtPollReply[45] = byte('r'); // r 443 | ArtPollReply[46] = byte('t'); // t 444 | ArtPollReply[47] = byte('G'); // G 445 | ArtPollReply[48] = byte('a'); // a 446 | ArtPollReply[49] = byte('t'); // t 447 | ArtPollReply[50] = byte('e'); // e 448 | ArtPollReply[51] = byte('O'); // O 449 | ArtPollReply[52] = byte('n'); // n 450 | ArtPollReply[53] = byte('e'); // e 451 | ArtPollReply[54] = byte(' '); // 452 | ArtPollReply[55] = byte('D'); // D 453 | ArtPollReply[56] = byte('M'); // M 454 | ArtPollReply[57] = byte('X'); // X 455 | ArtPollReply[58] = byte(' '); // 456 | ArtPollReply[59] = byte('1'); // 1 457 | ArtPollReply[60] = byte('.'); // . 458 | ArtPollReply[61] = byte('4'); // 4 459 | 460 | //ArtPollReply[108] = 0x00; // NodeReport 461 | 462 | const char *nodeReport = "#0001 [0000] ArtGateOne Art-Net Product. Good Boot."; 463 | for (int i = 0; i < strlen(nodeReport); i++) { 464 | ArtPollReply[108 + i] = nodeReport[i]; 465 | } 466 | 467 | ArtPollReply[172] = 0x00; // NumPorts Hi 468 | ArtPollReply[173] = 0x01; // NumPorts Lo 469 | 470 | ArtPollReply[174] = 0x80; // Port Types [0] 471 | ArtPollReply[175] = 0x00; // Port Types [1] 472 | ArtPollReply[176] = 0x00; // Port Types [2] 473 | ArtPollReply[177] = 0x00; // Port Types [3] 474 | 475 | ArtPollReply[178] = 0x08; // GoodInput [0] 476 | ArtPollReply[179] = 0x00; // GoodInput [1] 477 | ArtPollReply[180] = 0x00; // GoodInput [2] 478 | ArtPollReply[181] = 0x00; // GoodInput [3] 479 | 480 | ArtPollReply[182] = 0x80; // GoodOutputA [0] 481 | ArtPollReply[183] = 0x00; // GoodOutputA [1] 482 | ArtPollReply[184] = 0x00; // GoodOutputA [2] 483 | ArtPollReply[185] = 0x00; // GoodOutputA [3] 484 | 485 | ArtPollReply[186] = 0x00; // SwIn [0] 486 | ArtPollReply[187] = 0x00; // SwIn [1] 487 | ArtPollReply[188] = 0x00; // SwIn [2] 488 | ArtPollReply[189] = 0x00; // SwIn [3] 489 | 490 | ArtPollReply[190] = intU; // SwOut [0] 491 | ArtPollReply[191] = 0x00; // SwOut [1] 492 | ArtPollReply[192] = 0x00; // SwOut [2] 493 | ArtPollReply[193] = 0x00; // SwOut [3] 494 | 495 | ArtPollReply[194] = 0x00; // AcnPriority 496 | 497 | ArtPollReply[195] = 0x00; // SwMacro 498 | 499 | ArtPollReply[196] = 0x00; // SwRemote 500 | 501 | ArtPollReply[197] = 0x00; // Spare 502 | ArtPollReply[198] = 0x00; // Spare 503 | ArtPollReply[199] = 0x00; // Spare 504 | 505 | ArtPollReply[200] = 0x00; // Style 506 | 507 | ArtPollReply[201] = mac[0]; // MAC HI 508 | ArtPollReply[202] = mac[1]; // MAC 509 | ArtPollReply[203] = mac[2]; // MAC 510 | ArtPollReply[204] = mac[3]; // MAC 511 | ArtPollReply[205] = mac[4]; // MAC 512 | ArtPollReply[206] = mac[5]; // MAC LO 513 | 514 | ArtPollReply[207] = 0x00; // BIND IP 0 515 | ArtPollReply[208] = 0x00; // BIND IP 1 516 | ArtPollReply[209] = 0x00; // BIND IP 2 517 | ArtPollReply[210] = 0x00; // BIND IP 3 518 | ArtPollReply[211] = 0x00; // BInd Index 519 | 520 | ArtPollReply[212] = 0x0D; // Status2 521 | if (EEPROM.read(512) == 1) { 522 | ArtPollReply[212] = 0x0F; // DHCP USED 523 | } 524 | 525 | ArtPollReply[213] = 0x00; // GoodOutputB [0] 526 | ArtPollReply[214] = 0x00; // GoodOutputB [1] 527 | ArtPollReply[215] = 0x00; // GoodOutputB [2] 528 | ArtPollReply[216] = 0x00; // GoodOutputB [3] 529 | 530 | ArtPollReply[217] = 0x20; // Status3 531 | 532 | ArtPollReply[218] = 0x00; // DefaulRespUID Hi 533 | ArtPollReply[219] = 0x00; // DefaulRespUID 534 | ArtPollReply[220] = 0x00; // DefaulRespUID 535 | ArtPollReply[221] = 0x00; // DefaulRespUID 536 | ArtPollReply[222] = 0x00; // DefaulRespUID 537 | ArtPollReply[223] = 0x00; // DefaulRespUID Lo 538 | 539 | ArtPollReply[224] = 0x00; // UserHi 540 | ArtPollReply[225] = 0x00; // UserLo 541 | 542 | ArtPollReply[226] = 0x00; // RefreshRateHi 543 | ArtPollReply[227] = 0x00; // RefreshRateLo 544 | 545 | //Filler 11 x 8 Transmit as zero. For future expansion. 546 | 547 | return; 548 | } // end makeArtPollReply() 549 | 550 | void datadecode() { 551 | int j = 0; 552 | for (unsigned int i = 0; i <= datalen; i++) { 553 | if (strwww[i] == 61) { // jeśli znajdzie znak równości 554 | j++; 555 | i++; 556 | if (j == 1) { // DHCP 557 | EEPROM.update(512, (strwww[i] - 48)); 558 | } 559 | if (j == 2) { // IP ADDRES 560 | data = dataadd(i); 561 | EEPROM.update(513, data); 562 | i = i + 2; 563 | if (data >= 10) { 564 | i++; 565 | } 566 | if (data >= 100) { 567 | i++; 568 | } 569 | data = dataadd(i); 570 | EEPROM.update(514, data); 571 | i = i + 2; 572 | if (data >= 10) { 573 | i++; 574 | } 575 | if (data >= 100) { 576 | i++; 577 | } 578 | data = dataadd(i); 579 | EEPROM.update(515, data); 580 | i = i + 2; 581 | if (data >= 10) { 582 | i++; 583 | } 584 | if (data >= 100) { 585 | i++; 586 | } 587 | data = dataadd(i); 588 | EEPROM.update(516, data); 589 | } 590 | if (j == 3) { // SUBNET 591 | data = dataadd(i); 592 | EEPROM.update(517, data); 593 | i = i + 2; 594 | if (data >= 10) { 595 | i++; 596 | } 597 | if (data >= 100) { 598 | i++; 599 | } 600 | data = dataadd(i); 601 | EEPROM.update(518, data); 602 | i = i + 2; 603 | if (data >= 10) { 604 | i++; 605 | } 606 | if (data >= 100) { 607 | i++; 608 | } 609 | data = dataadd(i); 610 | EEPROM.update(519, data); 611 | i = i + 2; 612 | if (data >= 10) { 613 | i++; 614 | } 615 | if (data >= 100) { 616 | i++; 617 | } 618 | data = dataadd(i); 619 | EEPROM.update(520, data); 620 | } 621 | if (j == 4) { // GATEWAY 622 | data = dataadd(i); 623 | EEPROM.update(521, data); 624 | i = i + 2; 625 | if (data >= 10) { 626 | i++; 627 | } 628 | if (data >= 100) { 629 | i++; 630 | } 631 | data = dataadd(i); 632 | EEPROM.update(522, data); 633 | i = i + 2; 634 | if (data >= 10) { 635 | i++; 636 | } 637 | if (data >= 100) { 638 | i++; 639 | } 640 | data = dataadd(i); 641 | EEPROM.update(523, data); 642 | i = i + 2; 643 | if (data >= 10) { 644 | i++; 645 | } 646 | if (data >= 100) { 647 | i++; 648 | } 649 | data = dataadd(i); 650 | EEPROM.update(524, data); 651 | } 652 | if (j == 5) { // MAC 653 | EEPROM.update(525, datamac(i)); 654 | i = i + 5; 655 | EEPROM.update(526, datamac(i)); 656 | i = i + 5; 657 | EEPROM.update(527, datamac(i)); 658 | i = i + 5; 659 | EEPROM.update(528, datamac(i)); 660 | i = i + 5; 661 | EEPROM.update(529, datamac(i)); 662 | i = i + 5; 663 | EEPROM.update(530, datamac(i)); 664 | } 665 | if (j == 6) { // NET 666 | data = dataadd(i); 667 | EEPROM.update(531, data); 668 | intN = data; // NET 669 | } 670 | if (j == 7) { // SUBNET 671 | data = dataadd(i); 672 | EEPROM.update(532, data); 673 | intS = data; // Subnet 674 | } 675 | if (j == 8) { // UNIVERSE 676 | data = dataadd(i); 677 | EEPROM.update(533, data); 678 | intU = data; // Universe 679 | intUniverse = ((intS * 16) + intU); 680 | } 681 | if (j == 9) { // SCENE 682 | int data = (strwww[i] - 48); 683 | if (data <= 1) { 684 | EEPROM.update(534, data); 685 | } else { 686 | EEPROM.update(534, 1); 687 | // nagraj data do eprom 688 | for (i = 0; i <= 511; i++) { 689 | EEPROM.update(i, ArduinoDmx0.TxBuffer[i]); 690 | } 691 | } 692 | } 693 | } 694 | } 695 | } // end datadecode() 696 | 697 | int dataadd(int i) { 698 | data = 0; 699 | while (strwww[i] != 38 && strwww[i] != 46) { 700 | data = ((data * 10) + (strwww[i] - 48)); 701 | i++; 702 | } 703 | return data; 704 | } // end dataadd() 705 | 706 | int datamac(int i) { 707 | data = strwww[i]; 708 | if (data <= 57) { 709 | data = data - 48; 710 | } else if (data >= 65) { 711 | data = data - 55; 712 | } 713 | 714 | data = data * 16; 715 | 716 | if (strwww[i + 1] <= 57) { 717 | data = data + (strwww[i + 1] - 48); 718 | } else if (strwww[i + 1] >= 65) { 719 | data = data + (strwww[i + 1] - 55); 720 | } 721 | return data; 722 | } // end datamac() 723 | 724 | void displaydata() { 725 | //oled.clear(); 726 | //oled.print(" IP : "); 727 | //oled.println(Ethernet.localIP()); 728 | 729 | //if (I2C_ADDRESS == 0x3D) { 730 | //oled.print(" Mask: "); 731 | //oled.println(Ethernet.subnetMask()); 732 | 733 | //oled.print(" Net "); 734 | //oled.print(intN, HEX); 735 | //oled.print(" Sub "); 736 | //oled.print(intS, HEX); 737 | //oled.print(" Uni "); 738 | //oled.println(intU, HEX); 739 | //} 740 | 741 | //oled.print(" Universe "); 742 | //oled.print((intUniverse + (intN * 256))); 743 | 744 | if (EEPROM.read(534) == 1) { 745 | //oled.println(" BS"); 746 | } else { 747 | //oled.println(); 748 | } 749 | return; 750 | } // end displaydata() 751 | 752 | void incrementCounter() { 753 | static int counter = 0; // Static variable to retain the value between function calls 754 | counter++; // Increment the counter 755 | 756 | if (counter > 9999) { 757 | counter = 0; // Reset the counter to 0 after reaching 9999 758 | } 759 | 760 | // Convert the number to a character array (string) 761 | char buffer[5]; // Array to store the result 762 | snprintf(buffer, sizeof(buffer), "%04d", counter); // The format "%04d" ensures leading zeros in the number 763 | 764 | // Write the digits as characters to the ArtPollReply variables 765 | ArtPollReply[115] = buffer[0]; 766 | ArtPollReply[116] = buffer[1]; 767 | ArtPollReply[117] = buffer[2]; 768 | ArtPollReply[118] = buffer[3]; 769 | } // end incrementCounter() 770 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ArtGateOne-DMX 2 | This is simple artnet node. 3 | 4 | 5 | Required: 6 | Arduino UNO 7 | 8 | Ethernet Shield with W5100/W5500 9 | 10 | OLED display 128x32 I2C 11 | 12 | module with max485 13 | 14 | --------------------------------------- 15 | 16 | Universal Ethernet to DMX Interface 17 | 18 | ONE DMX512 Port 19 | 20 | Art-Net streaming DMX support 21 | 22 | Can be used with any Art-Net compliant console or DMX software 23 | 24 | Universe selectable by web browser 25 | 26 | 27 | Stand-alone DMX buffer mode 28 | 29 | --------------------------------------- 30 | 31 | WIRING 32 | 33 | OLED DISPLAY I2C 34 | 35 | VCC --> 5v or 3.3v 36 | 37 | GND --> GND 38 | 39 | SCL --> SCL 40 | 41 | SDA --> SDA 42 | 43 | ---------- 44 | MAX485 module 45 | 46 | RO --> not connnected 47 | 48 | RE + DE + VCC --> 5v (or VCC --> +5 , and RE + DE --> D2 PIN) 49 | 50 | DI --> TX (D1 PIN) 51 | 52 | GND --> GND 53 | 54 | A --> DMX OUT 55 | 56 | B --> DMX OUT 57 | 58 | 59 | 60 | ------- 61 | OLED REQUIRED TO CORRECT WORK 62 | 63 | 64 | IF U DONT HAVE OLED DISPLAY _ USE NO OLED VERSION 65 | 66 | 67 | ---------- 68 | 69 | U can configure it - use web browser - enter node ip (default 2.0.0.10) 70 | 71 | A3 pin to Ground when boot = Factory Reset 72 | 73 | Due to the limited amount of Arduino memory - the program recognizes only full ArtDMX frames - containing 512 channels, and ArtPool packages. 74 | 75 | ----------- 76 | "Art-Net™ Designed by and Copyright Artistic Licence Engineering Ltd" 77 | 78 | ----------- 79 | v1.4.6 80 | Update of the ArtPollReply frame for Art-Net 4 Protocol Release V1.4 Document Revision 1.4dh 19/7/2023 81 | Changes in DHCP and Static configuration storage 82 | Change of memory number on first startup 83 | Change of favicon. 84 | 85 | Web configuration not work on Firefox - use Edge,Chrome,Opera ... 86 | 87 | 88 | ----- 89 | 90 | -------------------------------------------------------------------------------- /libraries/Dmx/examples/Dmx_Muxer/Dmx_Muxer.pde: -------------------------------------------------------------------------------- 1 | /************************************************************************************************************* 2 | * 3 | * Title : Example DMX Muxer with channel patch for Arduino 4 universes DMX library. 4 | * Version : v 0.3 5 | * Last updated : 07.07.2012 6 | * Target : Arduino mega 2560, Arduino mega 1280 7 | * Author : Toni Merino - merino.toni at gmail.com 8 | * Web : www.deskontrol.net/blog 9 | * 10 | **************************************************************************************************************/ 11 | #include // comment/uncomment #define USE_UARTx in lib_dmx.h as needed 12 | 13 | // This sample get the first 200 channels from universe 1 + the first 200 channels from universe 2, and write all 14 | // to universe 3 (addresses 1-200 from universe 2 are converted to 201-400) 15 | 16 | //********************************************************************************************************* 17 | // New DMX modes *** EXPERIMENTAL *** 18 | //********************************************************************************************************* 19 | #define DMX512 (0) // (250 kbaud - 2 to 512 channels) Standard USITT DMX-512 20 | #define DMX1024 (1) // (500 kbaud - 2 to 1024 channels) Completely non standard - TESTED ok 21 | #define DMX2048 (2) // (1000 kbaud - 2 to 2048 channels) called by manufacturers DMX1000K, DMX 4x or DMX 1M ??? 22 | 23 | void setup() 24 | { 25 | 26 | ArduinoDmx1.set_control_pin(24); // Arduino output pin for MAX485 input/output control (connect to MAX485-1 pins 2-3) 27 | ArduinoDmx2.set_control_pin(26); // Arduino output pin for MAX485 input/output control (connect to MAX485-2 pins 2-3) 28 | ArduinoDmx3.set_control_pin(28); // Arduino output pin for MAX485 input/output control (connect to MAX485-3 pins 2-3) 29 | 30 | ArduinoDmx1.set_rx_address(1); // set rx1 start address 31 | ArduinoDmx2.set_rx_address(1); // set rx2 start address 32 | ArduinoDmx3.set_tx_address(1); // set tx start address 33 | 34 | ArduinoDmx1.set_rx_channels(200); // 2 to 2048!! channels in DMX1000K (512 in standard mode) See lib_dmx.h *** new *** EXPERIMENTAL 35 | ArduinoDmx2.set_rx_channels(200); // 2 to 2048!! channels in DMX1000K (512 in standard mode) See lib_dmx.h *** new *** EXPERIMENTAL 36 | ArduinoDmx3.set_tx_channels(400); // 2 to 2048!! channels in DMX1000K (512 in standard mode) See lib_dmx.h *** new *** EXPERIMENTAL 37 | 38 | // New parameter needed: DMX Mode 39 | ArduinoDmx1.init_rx(DMX512); // starts universe 1 as rx, standard DMX 512 - See lib_dmx.h, now support for DMX faster modes (DMX 1000K) 40 | ArduinoDmx2.init_rx(DMX512); // starts universe 2 as rx, standard DMX 512 - See lib_dmx.h, now support for DMX faster modes (DMX 1000K) 41 | ArduinoDmx3.init_tx(DMX512); // starts universe 3 as tx, standard DMX 512 - See lib_dmx.h, now support for DMX faster modes (DMX 1000K) 42 | 43 | }//end setup() 44 | 45 | void loop() 46 | { 47 | // copy 200 channels from rx buffer 1 to tx buffer 3 48 | memcpy((void *)ArduinoDmx3.TxBuffer, (void *)ArduinoDmx1.RxBuffer, 200); 49 | 50 | // copy 200 channels from rx buffer 2 to tx buffer 3, position 200 (patch from 1-200 to 201-400) 51 | memcpy((void *)&ArduinoDmx3.TxBuffer[200], (void *)ArduinoDmx2.RxBuffer, 200); 52 | 53 | }//end loop() 54 | 55 | -------------------------------------------------------------------------------- /libraries/Dmx/examples/Dmx_Muxer_HTP/Dmx_Muxer_HTP.pde: -------------------------------------------------------------------------------- 1 | /************************************************************************************************************* 2 | * 3 | * Title : Example HTP DMX Muxer for Arduino 4 universes DMX library. 4 | * Version : v 0.3 5 | * Last updated : 07.07.2012 6 | * Target : Arduino mega 2560, Arduino mega 1280 7 | * Author : Toni Merino - merino.toni at gmail.com 8 | * Web : www.deskontrol.net/blog 9 | * 10 | **************************************************************************************************************/ 11 | #include // comment/uncomment #define USE_UARTx in lib_dmx.h as needed 12 | 13 | // This sample get 512 channels from universe 1 + 512 channels from universe 2, 14 | // and write the highgest value to universe 3 15 | 16 | //********************************************************************************************************* 17 | // New DMX modes *** EXPERIMENTAL *** 18 | //********************************************************************************************************* 19 | #define DMX512 (0) // (250 kbaud - 2 to 512 channels) Standard USITT DMX-512 20 | #define DMX1024 (1) // (500 kbaud - 2 to 1024 channels) Completely non standard - TESTED ok 21 | #define DMX2048 (2) // (1000 kbaud - 2 to 2048 channels) called by manufacturers DMX1000K, DMX 4x or DMX 1M ??? 22 | 23 | void setup() 24 | { 25 | 26 | ArduinoDmx1.set_control_pin(24); // Arduino output pin for MAX485 input/output control (connect to MAX485-1 pins 2-3) 27 | ArduinoDmx2.set_control_pin(26); // Arduino output pin for MAX485 input/output control (connect to MAX485-2 pins 2-3) 28 | ArduinoDmx3.set_control_pin(28); // Arduino output pin for MAX485 input/output control (connect to MAX485-3 pins 2-3) 29 | 30 | ArduinoDmx1.set_rx_address(1); // set rx1 start address 31 | ArduinoDmx2.set_rx_address(1); // set rx2 start address 32 | ArduinoDmx3.set_tx_address(1); // set tx start address 33 | 34 | ArduinoDmx1.set_rx_channels(512); // 2 to 2048!! channels in DMX1000K (512 in standard mode) See lib_dmx.h *** new *** EXPERIMENTAL 35 | ArduinoDmx2.set_rx_channels(512); // 2 to 2048!! channels in DMX1000K (512 in standard mode) See lib_dmx.h *** new *** EXPERIMENTAL 36 | ArduinoDmx3.set_tx_channels(512); // 2 to 2048!! channels in DMX1000K (512 in standard mode) See lib_dmx.h *** new *** EXPERIMENTAL 37 | 38 | // New parameter needed in init_tx and init_rx: DMX Mode 39 | ArduinoDmx1.init_rx(DMX512); // starts universe 1 as rx, standard DMX 512 - See lib_dmx.h, now support for DMX faster modes (DMX 1000K) 40 | ArduinoDmx2.init_rx(DMX512); // starts universe 2 as rx, standard DMX 512 - See lib_dmx.h, now support for DMX faster modes (DMX 1000K) 41 | ArduinoDmx3.init_tx(DMX512); // starts universe 3 as tx, standard DMX 512 - See lib_dmx.h, now support for DMX faster modes (DMX 1000K) 42 | 43 | }//end setup() 44 | 45 | void loop() 46 | { 47 | for(int i=0;i<512;i++) //buffers 0 indexed (0-511) 48 | { 49 | // copy values from input buffers to output buffer 50 | // High value take priority ( HTP ) 51 | if(ArduinoDmx1.RxBuffer[i] > ArduinoDmx2.RxBuffer[i]) 52 | ArduinoDmx3.TxBuffer[i] = ArduinoDmx1.RxBuffer[i]; 53 | else 54 | ArduinoDmx3.TxBuffer[i] = ArduinoDmx2.RxBuffer[i]; 55 | } 56 | } //end loop() 57 | 58 | -------------------------------------------------------------------------------- /libraries/Dmx/examples/Dmx_Receive/Dmx_Receive.pde: -------------------------------------------------------------------------------- 1 | /************************************************************************************************************* 2 | * 3 | * Title : Example DMX Receiver 4 | * Version : v 0.3 5 | * Last updated : 07.07.2012 6 | * Target : Arduino mega 2560, Arduino mega 1280, Arduino nano 7 | * Author : Toni Merino - merino.toni at gmail.com 8 | * Web : www.deskontrol.net/blog 9 | * 10 | **************************************************************************************************************/ 11 | #include // comment/uncomment #define USE_UARTx in lib_dmx.h as needed 12 | 13 | // This example receive 4 channels from address 1 to 4 and write analog values to PWM pins 2 to 5 14 | 15 | // outputs update in main loop 16 | 17 | 18 | //********************************************************************************************************* 19 | // New DMX modes *** EXPERIMENTAL *** 20 | //********************************************************************************************************* 21 | #define DMX512 (0) // (250 kbaud - 2 to 512 channels) Standard USITT DMX-512 22 | #define DMX1024 (1) // (500 kbaud - 2 to 1024 channels) Completely non standard - TESTED ok 23 | #define DMX2048 (2) // (1000 kbaud - 2 to 2048 channels) called by manufacturers DMX1000K, DMX 4x or DMX 1M ??? 24 | 25 | void setup() 26 | { 27 | ArduinoDmx0.set_control_pin(22); // Arduino output pin for MAX485 input/output control (connect to MAX485 pins 2-3) 28 | ArduinoDmx0.set_rx_address(1); // set rx0 dmx start address 29 | ArduinoDmx0.set_rx_channels(4); // number of rx channels 30 | ArduinoDmx0.init_rx(DMX512); // starts universe 0 as rx, NEW Parameter DMX mode 31 | 32 | } //end setup() 33 | 34 | void loop() 35 | { 36 | //write values from dmx channels 1-4 universe 0 to arduino pwm pins 2-5 37 | analogWrite(2, ArduinoDmx0.RxBuffer[0]); //buffers 0 indexed 38 | analogWrite(3, ArduinoDmx0.RxBuffer[1]); 39 | analogWrite(4, ArduinoDmx0.RxBuffer[2]); 40 | analogWrite(5, ArduinoDmx0.RxBuffer[3]); 41 | } //end loop() 42 | 43 | -------------------------------------------------------------------------------- /libraries/Dmx/examples/Dmx_Receive_chained/Dmx_Receive_chained.pde: -------------------------------------------------------------------------------- 1 | /************************************************************************************************************* 2 | * 3 | * Title : Example DMX mode conversion and reception with 3 Universes chained 4 | * Version : v 0.3 5 | * Last updated : 07.07.2012 6 | * Target : Arduino mega 2560, Arduino mega 1280 7 | * Author : Toni Merino - merino.toni at gmail.com 8 | * Web : www.deskontrol.net/blog 9 | * 10 | **************************************************************************************************************/ 11 | #include // comment/uncomment #define USE_UARTx in lib_dmx.h as needed 12 | 13 | // This example test 3 universes at one time with diferent DMX modes: RX-3 DMX-512 - TX-2 DMX-1000K - RX-1 DMX-1000K 14 | // and handle 512 input channels + 512 output channels + 512 input channels, asincronous data updates in main loop. 15 | // GoooOOO Arduino 16 | 17 | // *** Place a wire loop between output pin of universe 2 (Arduino pin 16 - TX2) and universe 1 input pin (Arduino pin 19 - RX1) *** 18 | 19 | // Signal from external controller, inputs at universe 3 RX, copies universe 3 input buffer to universe 2 output buffer and loops 20 | // with a wire to universe 1 input, then received data on universe 1 is write to analog output pins... 21 | // (all proccess with 512 channels, but only 4 DMX channels are written to Arduino PWM outputs) 22 | 23 | // Remember: 24 | // Standard DMX-512 signal from controller is applied to universe 3 input pin (Arduino pin 15 - RX3), data received in 25 | // universe 3 INPUT buffer are copied in main loop to universe 2 OUTPUT buffer, and transmitted by universe 2 in DMX-1000K mode, 26 | // then received by universe 1 in DMX-1000K mode (via the loop wire), and received values from first 4 channels written 27 | // to Arduino PWM pins 2 to 5... Enjoy ;) 28 | 29 | // Is this useful??? 30 | // Advantages are clear, DMX-1000K is 4 times faster than USITT DMX512, 4 times faster is 168 Hz refresh rate with 512 channels, 31 | // or 4 times faster is 4 times more channels in one universe at DMX standard refresh rate of 42 Hz. 32 | // Many manufacturers are producing led matrix and other led systems and controllers with unknow (for me) specification 33 | // called DMX-1000K: unoficial?, but standard de facto... 34 | 35 | // If you have any information about strange DMX modes used by led lighting, (DMX derivates like 1536 channels mode, modes 36 | // with/without break and other funny modes, not SPI) please contact me. 37 | 38 | //********************************************************************************************************* 39 | // New DMX modes *** EXPERIMENTAL *** 40 | //********************************************************************************************************* 41 | #define DMX512 (0) // (250 kbaud - 2 to 512 channels) Standard USITT DMX-512 42 | #define DMX1024 (1) // (500 kbaud - 2 to 1024 channels) Completely non standard - TESTED ok 43 | #define DMX2048 (2) // (1000 kbaud - 2 to 2048 channels) called by manufacturers DMX1000K, DMX 4x or DMX 1M ??? 44 | 45 | #define CHANNELS (512) 46 | 47 | void setup() 48 | { 49 | ArduinoDmx3.set_rx_address(1); // set RX 3 DMX start address 50 | ArduinoDmx3.set_rx_channels(CHANNELS); // number of RX channels universe 3 51 | ArduinoDmx3.init_rx( DMX512 ); // starts universe 3 as RX (DMX input from external controller), DMX mode: standard USITT DMX-512 52 | 53 | ArduinoDmx2.set_tx_address(1); // set TX 2 DMX start address 54 | ArduinoDmx2.set_tx_channels(CHANNELS); // number of TX channels 55 | ArduinoDmx2.init_tx( DMX2048 ); // starts universe 2 as TX (wire loop to universe 1), DMX mode: DMX2048 (DMX1000K) 56 | 57 | ArduinoDmx1.set_rx_address(1); // set RX 1 DMX start address 58 | ArduinoDmx1.set_rx_channels(CHANNELS); // number of RX channels 59 | ArduinoDmx1.init_rx( DMX2048 ); // starts universe 1 as RX (wire loop from universe 2), DMX mode: DMX2048 (DMX1000K) 60 | 61 | } //end setup() 62 | 63 | void loop() 64 | { 65 | // copy data from RX 3 buffer to TX 2 buffer 66 | memcpy((void *)ArduinoDmx2.TxBuffer, (void *)ArduinoDmx3.RxBuffer, CHANNELS); 67 | 68 | // write values from RX 1 buffer, (dmx channels 1-4 only, to arduino pwm pins 2-5) 69 | analogWrite(2, ArduinoDmx1.RxBuffer[0]); // DMX channel 1 (buffers 0 indexed) 70 | analogWrite(3, ArduinoDmx1.RxBuffer[1]); 71 | analogWrite(4, ArduinoDmx1.RxBuffer[2]); 72 | analogWrite(5, ArduinoDmx1.RxBuffer[3]); 73 | } //end loop() 74 | 75 | -------------------------------------------------------------------------------- /libraries/Dmx/examples/Dmx_Receive_chained_2048/Dmx_Receive_chained_2048.pde: -------------------------------------------------------------------------------- 1 | /************************************************************************************************************* 2 | * 3 | * Title : Example DMX mode conversion and reception with 3 Universes chained 4 | * Version : v 0.3 5 | * Last updated : 07.07.2012 6 | * Target : Arduino mega 2560, Arduino mega 1280 7 | * Author : Toni Merino - merino.toni at gmail.com 8 | * Web : www.deskontrol.net/blog 9 | * 10 | **************************************************************************************************************/ 11 | #include // comment/uncomment #define USE_UARTx in lib_dmx.h as needed 12 | 13 | // This example test 3 universes at one time with diferent DMX modes: RX-3 DMX-512 - TX-2 DMX1000K - RX-1 DMX1000K 14 | // and handle 512 input channels + 2048 output channels + 2048 input channels, asincronous data updates in main loop. 15 | // GoooOOO Arduino 16 | 17 | // *** Place a wire loop between output pin of universe 2 (Arduino pin 16 - TX2) and universe 1 input pin (Arduino pin 19 - RX1) *** 18 | 19 | // Signal from external controller, inputs at universe 3 RX, copies universe 3 input buffer to universe 2 output buffer and loops 20 | // with a wire to universe 1 input, then received data on universe 1 is write to analog output pins... 21 | 22 | // Remember: 23 | // Standard DMX-512 signal from external controller is applied to MAX 485 in universe 3 input pin (Arduino pin 15 - RX3), data received in 24 | // universe 3 INPUT buffer are copied in main loop to universe 2 OUTPUT buffer (4 times to fill 2048 channels), and transmitted 25 | // by universe 2 in DMX-1000K (2048 channels) mode, then received by universe 1 in DMX-1000K (2048 channels) mode (via the loop wire), 26 | // and received value from original input channel 512 written to PWM pins 2 to 5. 27 | 28 | // And voila, our original value from input channel 512 is now at DMX-1000K channels 512-1024-1536-2048, Enjoy ;) 29 | 30 | // Is this useful??? 31 | // Advantages are clear, DMX-1000K is 4 times faster than USITT DMX512, 4 times faster is 168 Hz refresh rate with 512 channels, 32 | // or 4 times faster is 4 times more channels in one universe at DMX standard refresh rate of 42 Hz. 33 | // Many manufacturers are producing led matrix and other led systems and controllers with unknow (for me) specification 34 | // called DMX-1000K: unoficial?, but standard de facto... 35 | 36 | // If you have any information about strange DMX modes used by led lighting, (DMX derivates like 1536 channels mode, modes 37 | // with/without break and other funny modes, not SPI) please contact me. 38 | 39 | //********************************************************************************************************* 40 | // New DMX modes *** EXPERIMENTAL *** 41 | //********************************************************************************************************* 42 | #define DMX512 (0) // (250 kbaud - 2 to 512 channels) Standard USITT DMX-512 43 | #define DMX1024 (1) // (500 kbaud - 2 to 1024 channels) Completely non standard - TESTED ok 44 | #define DMX2048 (2) // (1000 kbaud - 2 to 2048 channels) called by manufacturers DMX1000K, DMX 4x or DMX 1M ??? 45 | 46 | #define CHANNELS (512) 47 | 48 | void setup() 49 | { 50 | ArduinoDmx3.set_rx_address(1); // set RX 3 DMX start address 51 | ArduinoDmx3.set_rx_channels(CHANNELS); // number of RX channels universe 3 52 | ArduinoDmx3.init_rx( DMX512 ); // starts universe 3 as RX (DMX input from external controller), DMX mode: standard USITT DMX-512 53 | 54 | ArduinoDmx2.set_tx_address(1); // set TX 2 DMX start address 55 | ArduinoDmx2.set_tx_channels(CHANNELS * 4); // number of TX channels 56 | ArduinoDmx2.init_tx( DMX2048 ); // starts universe 2 as TX (wire loop to universe 1), DMX mode: DMX2048 (DMX1000K) 57 | 58 | ArduinoDmx1.set_rx_address(1); // set RX 1 DMX start address 59 | ArduinoDmx1.set_rx_channels(CHANNELS * 4); // number of RX channels 60 | ArduinoDmx1.init_rx( DMX2048 ); // starts universe 1 as RX (wire loop from universe 2), DMX mode: DMX2048 (DMX1000K) 61 | 62 | } //end setup() 63 | 64 | void loop() 65 | { 66 | // copy data from RX 3 buffer to TX 2 buffer 4 times (repeat values 4 times in order to fill 2048 output channels of DMX1000K) 67 | 68 | // To channels 1-512 69 | memcpy((void *)ArduinoDmx2.TxBuffer, (void *)ArduinoDmx3.RxBuffer, CHANNELS); 70 | // To channels 513-1024 71 | memcpy((void *)&ArduinoDmx2.TxBuffer[512], (void *)ArduinoDmx3.RxBuffer, CHANNELS); 72 | // To channels 1025-1536 73 | memcpy((void *)&ArduinoDmx2.TxBuffer[1024], (void *)ArduinoDmx3.RxBuffer, CHANNELS); 74 | // To channels 1537-2048 75 | memcpy((void *)&ArduinoDmx2.TxBuffer[1536], (void *)ArduinoDmx3.RxBuffer, CHANNELS); 76 | 77 | // write values from RX 1 buffer, (dmx channel 512 only, to arduino pwm pins 2-5) 78 | analogWrite(2, ArduinoDmx1.RxBuffer[2047]); // DMX input channel 512 -> DMX1000K channel 2048 79 | analogWrite(3, ArduinoDmx1.RxBuffer[1535]); // DMX input channel 512 -> DMX1000K channel 1536 80 | analogWrite(4, ArduinoDmx1.RxBuffer[1023]); // DMX input channel 512 -> DMX1000K channel 1024 81 | analogWrite(5, ArduinoDmx1.RxBuffer[511]); // DMX input channel 512 -> DMX1000K channel 512 82 | } //end loop() 83 | 84 | -------------------------------------------------------------------------------- /libraries/Dmx/examples/Dmx_Receive_interrupts/Dmx_Receive_interrupts.pde: -------------------------------------------------------------------------------- 1 | /************************************************************************************************************* 2 | * 3 | * Title : Example DMX Receiver with received frame interrupt 4 | * Version : v 0.3 5 | * Last updated : 07.07.2012 6 | * Target : Arduino mega 2560, Arduino mega 1280, Arduino nano 7 | * Author : Toni Merino - merino.toni at gmail.com 8 | * Web : www.deskontrol.net/blog 9 | * 10 | **************************************************************************************************************/ 11 | #include // comment/uncomment #define USE_UARTx in lib_dmx.h as needed 12 | 13 | // This example receive 4 channels from address 1 to 4 and write analog values to PWM pins 2 to 5 14 | 15 | //********************************************************************************************************* 16 | // *** NEW *** 17 | //********************************************************************************************************* 18 | // ArduinoDmxN.attachRXInterrupt(my_rx_ISR) don't waste time updating values in main loop 19 | // ArduinoDmxN.attachTXInterrupt(my_tx_ISR) don't waste time updating values in main loop 20 | 21 | //********************************************************************************************************* 22 | // New DMX modes *** EXPERIMENTAL *** 23 | //********************************************************************************************************* 24 | #define DMX512 (0) // (250 kbaud - 2 to 512 channels) Standard USITT DMX-512 25 | #define DMX1024 (1) // (500 kbaud - 2 to 1024 channels) Completely non standard - TESTED ok 26 | #define DMX2048 (2) // (1000 kbaud - 2 to 2048 channels) called by manufacturers DMX1000K, DMX 4x or DMX 1M ??? 27 | 28 | void setup() 29 | { 30 | 31 | ArduinoDmx0.set_control_pin (22); // Arduino output pin for MAX485 input/output control (connect to MAX485 pins 2-3) 32 | ArduinoDmx0.set_rx_address (1); // set rx0 dmx start address 33 | ArduinoDmx0.set_rx_channels (4); // number of rx channels 34 | 35 | // *** NEW *** attach RX service routine here, fired when all channels in one universe are received. 36 | ArduinoDmx0.attachRXInterrupt (frame_received); 37 | //ArduinoDmx1.attachRXInterrupt (frame_received); 38 | //ArduinoDmx2.attachRXInterrupt (frame_received); 39 | //ArduinoDmx3.attachRXInterrupt (frame_received); 40 | 41 | // *** NEW *** attach TX service routine here, fired when all channels in one universe are send. 42 | // ArduinoDmx0.attachTXInterrupt (frame_send); 43 | // ArduinoDmx1.attachTXInterrupt (frame_send); 44 | // ArduinoDmx2.attachTXInterrupt (frame_send); 45 | // ArduinoDmx3.attachTXInterrupt (frame_send); 46 | 47 | ArduinoDmx0.init_rx (DMX512); // starts universe 0 as rx, *** NEW Parameter DMX mode *** 48 | 49 | } //end setup() 50 | 51 | void loop() 52 | { 53 | 54 | // YOUR CODE HERE 55 | 56 | } //end loop() 57 | 58 | void frame_received(uint8_t universe) // Custom ISR: fired when all channels in one universe are received 59 | { 60 | if (universe == 0) // USART0 61 | { 62 | //write values from dmx channels 1-4 universe 0 to arduino pwm pins 2-5 63 | analogWrite(2, ArduinoDmx0.RxBuffer[0]); //buffers 0 indexed 64 | analogWrite(3, ArduinoDmx0.RxBuffer[1]); 65 | analogWrite(4, ArduinoDmx0.RxBuffer[2]); 66 | analogWrite(5, ArduinoDmx0.RxBuffer[3]); 67 | } 68 | } // end of ISR 69 | 70 | /* 71 | void frame_send(uint8_t universe) // Custom ISR: fired when all channels in one universe are send 72 | { 73 | if (universe == 0) // USART0 74 | { 75 | // ***** 76 | } 77 | else if (universe == 1) // USART1 78 | { 79 | // ***** 80 | } 81 | } // end of ISR 82 | */ -------------------------------------------------------------------------------- /libraries/Dmx/lib_dmx.cpp: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * 3 | * Title : Arduino DMX512 library. 4 input/output universes. 4 | * Version : v 0.3 beta 5 | * Last updated : 07.07.2012 6 | * Target : Arduino mega 2560, Arduino mega 1280, Arduino nano (1 universe) 7 | * Author : Toni Merino - merino.toni at gmail.com 8 | * Web : www.deskontrol.net/blog 9 | * 10 | * Based on ATmega8515 Dmx library written by Hendrik Hoelscher, www.hoelscher-hi.de 11 | *************************************************************************** 12 | 13 | This program is free software; you can redistribute it and/or 14 | modify it under the terms of the GNU General Public License 15 | as published by the Free Software Foundation; either version2 of 16 | the License, or (at your option) any later version. 17 | 18 | This program is distributed in the hope that it will be useful, 19 | but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 21 | General Public License for more details. 22 | 23 | If you have no copy of the GNU General Public License, write to the 24 | Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 25 | 26 | For other license models, please contact the author. 27 | 28 | ;***************************************************************************/ 29 | #include "lib_dmx.h" 30 | 31 | #if defined(USE_UART0) 32 | CArduinoDmx ArduinoDmx0(0); 33 | #endif 34 | #if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) 35 | #if defined(USE_UART1) 36 | CArduinoDmx ArduinoDmx1(1); 37 | #endif 38 | #if defined(USE_UART2) 39 | CArduinoDmx ArduinoDmx2(2); 40 | #endif 41 | #if defined(USE_UART3) 42 | CArduinoDmx ArduinoDmx3(3); 43 | #endif 44 | #endif 45 | 46 | // *************** DMX Transmision Initialisation **************** 47 | void CArduinoDmx::init_tx(uint8_t mode) 48 | { 49 | cli(); //disable interrupts 50 | stop_dmx(); //stop uart 51 | dmx_mode = mode; 52 | set_speed(dmx_mode); 53 | 54 | if(control_pin != -1) 55 | { 56 | pinMode(control_pin,OUTPUT); // max485 I/O control 57 | digitalWrite(control_pin, HIGH); // set 485 as output 58 | } 59 | 60 | if(mUART == 0) 61 | { 62 | pinMode(1, OUTPUT); 63 | UBRR0H = 0; 64 | UBRR0L = speed_dmx; 65 | UCSR0A |= (1<= (RxBuffer + rx_channels)) //all ch received? 308 | { 309 | gRxState= IDLE; 310 | if (*RXisrCallback) RXisrCallback(mUART); // fire callback for read data 311 | } 312 | else 313 | { 314 | gRxPnt = RxPnt; 315 | } 316 | } 317 | } 318 | 319 | // *************** DMX Transmision ISR **************** 320 | #if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) 321 | #if defined(USE_UART0) 322 | ISR(USART0_TX_vect) 323 | { 324 | ArduinoDmx0.Process_ISR_TX(0); 325 | } 326 | #endif 327 | #if defined(USE_UART1) 328 | ISR(USART1_TX_vect) 329 | { 330 | ArduinoDmx1.Process_ISR_TX(1); 331 | } 332 | #endif 333 | #if defined(USE_UART2) 334 | ISR(USART2_TX_vect) 335 | { 336 | ArduinoDmx2.Process_ISR_TX(2); 337 | } 338 | #endif 339 | #if defined(USE_UART3) 340 | ISR(USART3_TX_vect) 341 | { 342 | ArduinoDmx3.Process_ISR_TX(3); 343 | } 344 | #endif 345 | #elif defined(__AVR_ATmega328P__) || defined(__AVR_ATmega168__) 346 | #if defined(USE_UART0) 347 | ISR(USART_TX_vect) 348 | { 349 | ArduinoDmx0.Process_ISR_TX(0); 350 | } 351 | #endif 352 | #endif 353 | 354 | 355 | void CArduinoDmx::Process_ISR_TX(uint8_t tx_isr_number) 356 | { 357 | TxState = gTxState; 358 | 359 | if(tx_isr_number == 0) 360 | { 361 | if (TxState == TXBREAK) //BREAK + MAB 362 | { 363 | UBRR0H = 0; 364 | UBRR0L = speed_break; 365 | UDR0 = 0; //send break 366 | gTxState = TXSTARTB; 367 | } 368 | else if (TxState == TXSTARTB) 369 | { 370 | UBRR0H = 0; 371 | UBRR0L = speed_dmx; 372 | UDR0 = 0; //send start byte 373 | gTxState = TXDATA; 374 | gCurTxCh = 0; 375 | } 376 | else 377 | { 378 | #if defined(USE_INTERBYTE_DELAY) 379 | delay_gap(); 380 | #endif 381 | CurTxCh = gCurTxCh; 382 | UDR0 = TxBuffer[CurTxCh++]; //send data 383 | if (CurTxCh == tx_channels) 384 | { 385 | if (*TXisrCallback) TXisrCallback(0); // fire callback for update data 386 | gTxState = TXBREAK; // new break if all ch sent 387 | } 388 | else 389 | { 390 | gCurTxCh = CurTxCh; 391 | } 392 | } 393 | } 394 | #if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) 395 | 396 | else if(tx_isr_number == 1) 397 | { 398 | if (TxState == TXBREAK) 399 | { 400 | UBRR1H = 0; 401 | UBRR1L = speed_break; 402 | UDR1 = 0; //send break 403 | gTxState = TXSTARTB; 404 | } 405 | else if (TxState == TXSTARTB) 406 | { 407 | UBRR1H = 0; 408 | UBRR1L = speed_dmx; 409 | UDR1 = 0; //send start byte 410 | gTxState = TXDATA; 411 | gCurTxCh = 0; 412 | } 413 | else 414 | { 415 | #if defined(USE_INTERBYTE_DELAY) 416 | delay_gap(); 417 | #endif 418 | CurTxCh = gCurTxCh; 419 | UDR1 = TxBuffer[CurTxCh++]; //send data 420 | if (CurTxCh == tx_channels) 421 | { 422 | if (*TXisrCallback) TXisrCallback(1); // fire callback for update data 423 | gTxState = TXBREAK; // new break if all ch sent 424 | } 425 | else 426 | { 427 | gCurTxCh = CurTxCh; 428 | } 429 | } 430 | } 431 | else if(tx_isr_number == 2) 432 | { 433 | if (TxState == TXBREAK) 434 | { 435 | UBRR2H = 0; 436 | UBRR2L = speed_break; 437 | UDR2 = 0; //send break 438 | gTxState = TXSTARTB; 439 | } 440 | else if (TxState == TXSTARTB) 441 | { 442 | UBRR2H = 0; 443 | UBRR2L = speed_dmx; 444 | UDR2 = 0; //send start byte 445 | gTxState = TXDATA; 446 | gCurTxCh = 0; 447 | } 448 | else 449 | { 450 | #if defined(USE_INTERBYTE_DELAY) 451 | delay_gap(); 452 | #endif 453 | CurTxCh = gCurTxCh; 454 | UDR2 = TxBuffer[CurTxCh++]; //send data 455 | if (CurTxCh == tx_channels) 456 | { 457 | if (*TXisrCallback) TXisrCallback(2); // fire callback for update data 458 | gTxState = TXBREAK; // new break if all ch sent 459 | } 460 | else 461 | { 462 | gCurTxCh = CurTxCh; 463 | } 464 | } 465 | } 466 | else if(tx_isr_number == 3) 467 | { 468 | if (TxState == TXBREAK) 469 | { 470 | UBRR3H = 0; 471 | UBRR3L = speed_break; 472 | UDR3 = 0; //send break 473 | gTxState = TXSTARTB; 474 | } 475 | else if (TxState == TXSTARTB) 476 | { 477 | UBRR3H = 0; 478 | UBRR3L = speed_dmx; 479 | UDR3 = 0; //send start byte 480 | gTxState = TXDATA; 481 | gCurTxCh = 0; 482 | } 483 | else 484 | { 485 | #if defined(USE_INTERBYTE_DELAY) 486 | delay_gap(); 487 | #endif 488 | CurTxCh = gCurTxCh; 489 | UDR3 = TxBuffer[CurTxCh++]; //send data 490 | if (CurTxCh == tx_channels) 491 | { 492 | if (*TXisrCallback) TXisrCallback(3); // fire callback for update data 493 | gTxState = TXBREAK; // new break if all ch sent 494 | } 495 | else 496 | { 497 | gCurTxCh = CurTxCh; 498 | } 499 | } 500 | } 501 | #endif 502 | } 503 | 504 | void CArduinoDmx::set_speed(uint8_t mode) 505 | { 506 | if(mode == 0) 507 | { 508 | speed_dmx = DMX_512; // DMX-512 (250 kbaud - 512 channels) Standard USITT DMX-512 509 | speed_break = BREAK_512; 510 | } 511 | else if(mode == 1) 512 | { 513 | speed_dmx = DMX_1024; // DMX-1024 (500 kbaud - 1024 channels) Completely non standard, but usefull ;) 514 | speed_break = BREAK_1024; 515 | } 516 | else if(mode == 2) 517 | { 518 | speed_dmx = DMX_2048; // DMX-2048 (1000 kbaud - 2048 channels) Used by manufacturers as DMX1000K, DMX-4x or DMX-1M ??? 519 | speed_break = BREAK_2048; 520 | } 521 | } 522 | 523 | #if defined(USE_INTERBYTE_DELAY) 524 | 525 | void CArduinoDmx::delay_gap() // rare cases of equipment non full DMX-512 compliant, need this 526 | { 527 | if(dmx_mode == 0) 528 | { 529 | _delay_us(IBG_512); 530 | } 531 | else if(dmx_mode == 1) 532 | { 533 | _delay_us(IBG_1024); 534 | } 535 | else if(dmx_mode == 2) 536 | { 537 | _delay_us(IBG_2048); 538 | } 539 | } 540 | #endif 541 | 542 | 543 | 544 | -------------------------------------------------------------------------------- /libraries/Dmx/lib_dmx.h: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * 3 | * Title : Arduino DMX512 library. 4 input/output universes. 4 | * Version : v 0.3 beta 5 | * Last updated : 07.07.2012 6 | * Target : Arduino mega 2560, Arduino mega 1280, Arduino nano (1 universe) 7 | * Author : Toni Merino - merino.toni at gmail.com 8 | * Web : www.deskontrol.net/blog 9 | * 10 | * Based on ATmega8515 Dmx library written by Hendrik Hoelscher, www.hoelscher-hi.de 11 | *************************************************************************** 12 | This program is free software; you can redistribute it and/or 13 | modify it under the terms of the GNU General Public License 14 | as published by the Free Software Foundation; either version2 of 15 | the License, or (at your option) any later version. 16 | 17 | This program is distributed in the hope that it will be useful, 18 | but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 20 | General Public License for more details. 21 | 22 | If you have no copy of the GNU General Public License, write to the 23 | Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 24 | 25 | For other license models, please contact the author. 26 | 27 | ;***************************************************************************/ 28 | #ifndef __INC_DMX_H 29 | #define __INC_DMX_H 30 | 31 | #include 32 | #include 33 | #include 34 | #include 35 | #if ARDUINO >= 100 36 | #include "Arduino.h" 37 | #else 38 | #include "WProgram.h" 39 | #endif 40 | 41 | //#define USE_INTERBYTE_DELAY // rare cases of equipment non full DMX-512 compliant, need this 42 | 43 | // *** comment UARTs not used *** 44 | #define USE_UART0 45 | //#define USE_UART1 46 | //#define USE_UART2 47 | //#define USE_UART3 48 | 49 | // New DMX modes *** EXPERIMENTAL *** 50 | #define DMX512 (0) // DMX-512 (250 kbaud - 512 channels) Standard USITT DMX-512 51 | #define DMX1024 (1) // DMX-1024 (500 kbaud - 1024 channels) Completely non standard - TESTED ok 52 | #define DMX2048 (2) // DMX-2048 (1000 kbaud - 2048 channels) called by manufacturers DMX1000K, DMX 4x or DMX 1M ??? 53 | 54 | // DMX-512 (250 kbaud - 512 channels) Standard USITT DMX-512 55 | #define IBG_512 (10) // interbyte gap [us] 56 | #define DMX_512 ((F_CPU/(250000*8))-1) // 250 kbaud 57 | #define BREAK_512 ( F_CPU/(100000*8)) // 90.9 kbaud 58 | 59 | // DMX-1024 (500 kbaud - 1024 channels) Completely non standard 60 | #define IBG_1024 (5) // interbyte gap [us] 61 | #define DMX_1024 ((F_CPU/(500000*8))-1) // 500 kbaud 62 | #define BREAK_1024 ( F_CPU/(200000*8)) // 181.8 kbaud 63 | 64 | // DMX-2048 (1000 kbaud - 2048 channels) Non standard, but used by manufacturers as DMX1000K or DMX-4x or DMX 1M ??? 65 | #define IBG_2048 (2) // interbyte gap [us] + nop's to reach 2.5 uS 66 | #define DMX_2048 ((F_CPU/(1000000*8))-1) // 1000 kbaud 67 | #define BREAK_2048 ( F_CPU/(400000*8)) // 363.6 kbaud 68 | 69 | // Inline assembly: do nothing for one clock cycle. 70 | #define nop() __asm__ __volatile__("nop") 71 | 72 | #ifdef __cplusplus 73 | extern "C" { 74 | #endif 75 | #if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) 76 | #if defined(USE_UART0) 77 | void USART0_RX_vect (void) __attribute__((__always_inline__)); 78 | void USART0_TX_vect (void) __attribute__((__always_inline__)); 79 | #endif 80 | #if defined(USE_UART1) 81 | void USART1_RX_vect (void) __attribute__((__always_inline__)); 82 | void USART1_TX_vect (void) __attribute__((__always_inline__)); 83 | #endif 84 | #if defined(USE_UART2) 85 | void USART2_RX_vect (void) __attribute__((__always_inline__)); 86 | void USART2_TX_vect (void) __attribute__((__always_inline__)); 87 | #endif 88 | #if defined(USE_UART3) 89 | void USART3_RX_vect (void) __attribute__((__always_inline__)); 90 | void USART3_TX_vect (void) __attribute__((__always_inline__)); 91 | #endif 92 | #elif defined(__AVR_ATmega328P__) || defined(__AVR_ATmega168__) 93 | #if defined(USE_UART0) 94 | void USART_RX_vect (void) __attribute__((__always_inline__)); 95 | void USART_TX_vect (void) __attribute__((__always_inline__)); 96 | #endif 97 | #endif 98 | #ifdef __cplusplus 99 | }; 100 | #endif 101 | 102 | class CArduinoDmx 103 | { 104 | #if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) 105 | #if defined(USE_UART0) 106 | friend void USART0_RX_vect (void); 107 | friend void USART0_TX_vect (void); 108 | #endif 109 | #if defined(USE_UART1) 110 | friend void USART1_RX_vect (void); 111 | friend void USART1_TX_vect (void); 112 | #endif 113 | #if defined(USE_UART2) 114 | friend void USART2_RX_vect (void); 115 | friend void USART2_TX_vect (void); 116 | #endif 117 | #if defined(USE_UART3) 118 | friend void USART3_RX_vect (void); 119 | friend void USART3_TX_vect (void); 120 | #endif 121 | #elif defined(__AVR_ATmega328P__) || defined(__AVR_ATmega168__) 122 | #if defined(USE_UART0) 123 | friend void USART_RX_vect (void); 124 | friend void USART_TX_vect (void); 125 | #endif 126 | #endif 127 | 128 | public: 129 | enum {IDLE, BREAK, STARTB, STARTADR}; // RX DMX states 130 | enum {TXBREAK, TXSTARTB, TXDATA}; // TX DMX states 131 | 132 | volatile uint8_t *RxBuffer; // array of RX DMX values 133 | volatile uint8_t *TxBuffer; // array of TX DMX values 134 | 135 | private: 136 | uint8_t gRxState; 137 | uint8_t *gRxPnt; 138 | uint8_t IndicatorCount; 139 | uint8_t USARTstate; 140 | uint8_t RxByte; 141 | uint8_t RxState; 142 | uint8_t mUART; 143 | uint8_t gTxState; 144 | uint16_t RxCount; 145 | uint16_t gCurTxCh; 146 | uint16_t rx_channels; // rx channels number 147 | uint16_t tx_channels; // tx channels number 148 | uint16_t rx_address; // rx start address 149 | uint16_t tx_address; // tx start address 150 | int8_t rx_led; // rx indicator led pin 151 | int8_t tx_led; // tx indicator led pin 152 | int8_t control_pin; // max485 input/output selection pin 153 | uint8_t dmx_mode; // Standard USITT DMX512 = 0, non standard DMX1024 = 1, non standard DMX2048 (DMX1000K) = 2 154 | uint8_t speed_dmx; 155 | uint8_t speed_break; 156 | uint16_t CurTxCh; 157 | uint8_t TxState; 158 | uint8_t *RxPnt; 159 | 160 | #if defined(USE_INTERBYTE_DELAY) 161 | void delay_gap (); 162 | #endif 163 | 164 | public: 165 | void stop_dmx (); 166 | void set_speed (uint8_t mode); 167 | void set_control_pin (int8_t pin) { control_pin = pin; } 168 | void init_rx (uint8_t mode); // Standard USITT DMX512 = 0, non standard DMX1024 = 1, non standard DMX2048 (DMX1000K) = 2 169 | void set_rx_address (uint16_t address) { rx_address = address; } 170 | void set_rx_channels (uint16_t channels) { rx_channels = channels; } 171 | void init_tx (uint8_t mode); // Standard USITT DMX512 = 0, non standard DMX1024 = 1, non standard DMX2048 (DMX1000K) = 2 172 | void set_tx_address (uint16_t address) { tx_address = address; } 173 | void set_tx_channels (uint16_t channels) { tx_channels = channels; } 174 | 175 | void attachTXInterrupt (void (*isr)(uint8_t uart)) { TXisrCallback = isr; } // register the user TX callback 176 | void attachRXInterrupt (void (*isr)(uint8_t uart)) { RXisrCallback = isr; } // register the user RX callback 177 | 178 | void (*TXisrCallback) (uint8_t uart); 179 | void (*RXisrCallback) (uint8_t uart); 180 | 181 | inline void Process_ISR_RX (uint8_t rx_isr_number); 182 | inline void Process_ISR_TX (uint8_t tx_isr_number); 183 | 184 | public: 185 | CArduinoDmx (uint8_t uart) { rx_address = 1; 186 | rx_channels = 8; 187 | tx_address = 1; 188 | tx_channels = 8; 189 | mUART = uart; } 190 | 191 | }; 192 | 193 | #if defined(USE_UART0) 194 | extern CArduinoDmx ArduinoDmx0; 195 | #endif 196 | #if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) 197 | #if defined(USE_UART1) 198 | extern CArduinoDmx ArduinoDmx1; 199 | #endif 200 | #if defined(USE_UART2) 201 | extern CArduinoDmx ArduinoDmx2; 202 | #endif 203 | #if defined(USE_UART3) 204 | extern CArduinoDmx ArduinoDmx3; 205 | #endif 206 | #endif 207 | 208 | #endif 209 | --------------------------------------------------------------------------------