Skip to content

Commit

Permalink
New async E131 backend.
Browse files Browse the repository at this point in the history
Updated WS2811 timing.
Added hostname configuration.
Consolidated web files (gulp).
  • Loading branch information
forkineye committed Jun 25, 2017
1 parent f8cafe3 commit 85c3b4f
Show file tree
Hide file tree
Showing 9 changed files with 70 additions and 52 deletions.
6 changes: 4 additions & 2 deletions Changelog.md
@@ -1,10 +1,12 @@

Changelog
=========
### 2.1
### 3.0-dev1
- Complete re-write of the web frontend. Requires a WebSockets capable browser.
- Migrated to ESPAsyncUDP for E131 parsing (E131 library updated).
- Increased WS2811 reset time from 50us to 300us to support newer WS2811 chips.
- Added hostname configuration.
- Added GBR and BGR color order for pixels.
- Changed WS2811 reset time from 50us to 80us to better support WS2811 clones.

### 2.0
- Added web based OTA update capability.
Expand Down
4 changes: 2 additions & 2 deletions ESPixelStick.h
Expand Up @@ -27,7 +27,7 @@
#endif

/* Name and version */
const char VERSION[] = "3.0-dev (20170623)";
const char VERSION[] = "3.0-dev1 (20170624)";

#define HTTP_PORT 80 /* Default web server port */
#define DATA_PIN 2 /* Pixel output - GPIO2 */
Expand Down Expand Up @@ -109,7 +109,7 @@ typedef struct {
} config_t;

/* Globals */
E131 e131;
E131Async e131(10); /* E131Async with X buffers */
testing_t testing;
config_t config;
uint32_t *seqError; /* Sequence error tracking for each universe */
Expand Down
63 changes: 33 additions & 30 deletions ESPixelStick.ino
Expand Up @@ -37,13 +37,14 @@ const char passphrase[] = "ENTER_PASSPHRASE_HERE";
#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <ESPAsyncTCP.h>
#include <ESPAsyncUDP.h>
#include <ESPAsyncWebServer.h>
#include <WiFiUdp.h>
//#include <WiFiUdp.h>
#include <ESP8266mDNS.h>
#include <ArduinoJson.h>
#include <Hash.h>
#include <SPI.h>
#include <E131.h>
#include <E131Async.h>
#include "ESPixelStick.h"
#include "EFUpdate.h"
#include "wshandler.h"
Expand Down Expand Up @@ -353,7 +354,7 @@ void dsNetworkConfig(JsonObject &json) {
if (!config.hostname.length()) {
char chipId[7] = { 0 };
snprintf(chipId, sizeof(chipId), "%06x", ESP.getChipId());
config.hostname = "esps_" + String(chipId);
config.hostname = "esps-" + String(chipId);
}
}

Expand Down Expand Up @@ -497,61 +498,62 @@ void saveConfig() {

/* Main Loop */
void loop() {
/* Reboot handler */
e131_packet_t packet;
// Reboot handler
if (reboot) {
delay(REBOOT_DELAY);
ESP.restart();
}

if (config.testmode == TestMode::DISABLED || config.testmode == TestMode::VIEW_STREAM) {
/* Parse a packet and update pixels */
if (e131.parsePacket()) {
if ((e131.universe >= config.universe) && (e131.universe <= uniLast)) {
/* Universe offset and sequence tracking */
uint8_t uniOffset = (e131.universe - config.universe);
if (e131.packet->sequence_number != seqTracker[uniOffset]++) {
// Parse a packet and update pixels
if (!e131.pbuff->isEmpty(e131.pbuff)) {
e131.pbuff->pull(e131.pbuff, &packet);
uint16_t universe = htons(packet.universe);
uint8_t *data = packet.property_values + 1;
if ((universe >= config.universe) && (universe <= uniLast)) {
// Universe offset and sequence tracking
uint8_t uniOffset = (universe - config.universe);
if (packet.sequence_number != seqTracker[uniOffset]++) {
seqError[uniOffset]++;
seqTracker[uniOffset] = e131.packet->sequence_number + 1;
seqTracker[uniOffset] = packet.sequence_number + 1;
}

/* Offset the channels if required */
// Offset the channels if required
uint16_t offset = 0;
offset = config.channel_start - 1;

/* Find start of data based off the Universe */
// Find start of data based off the Universe
int16_t dataStart = uniOffset * UNIVERSE_LIMIT - offset;

/* Calculate how much data we need for this buffer */
// Calculate how much data we need for this buffer
uint16_t dataStop = config.channel_count;
if ((dataStart + UNIVERSE_LIMIT) < dataStop)
dataStop = dataStart + UNIVERSE_LIMIT;

/* Set the data */
// Set the data
uint16_t buffloc = 0;
/* ignore data from start of first Universe before channel_start */
if(dataStart<0) {
dataStart=0;
buffloc=config.channel_start-1;

// ignore data from start of first Universe before channel_start
if (dataStart < 0) {
dataStart = 0;
buffloc = config.channel_start-1;
}

for (int i = dataStart; i < dataStop; i++) {
#if defined(ESPS_MODE_PIXEL)
pixels.setValue(i, e131.data[buffloc]);
pixels.setValue(i, data[buffloc]);
#elif defined(ESPS_MODE_SERIAL)
serial.setValue(i, e131.data[buffloc]);
serial.setValue(i, data[buffloc]);
#endif
buffloc++;
}
}
}
} else { //some other testmode
//keep feeding server so we don't overrun with packets
e131.parsePacket();

switch(config.testmode) {
} else { // Other testmodes
switch (config.testmode) {
case TestMode::STATIC: {
//continue to update color to whole string
// Continue to update color to whole string
uint16_t i = 0;
while (i <= config.channel_count - 3) {
#if defined(ESPS_MODE_PIXEL)
Expand Down Expand Up @@ -621,7 +623,7 @@ void loop() {
pixels.setValue(ch_offset++,255 - WheelPos * 3);
pixels.setValue(ch_offset, 0);
}
#elif defined(ESPS_MODE_SERIAL)
#elif defined(ESPS_MODE_SERIAL)
if (WheelPos < 85) {
serial.setValue(ch_offset++, 255 - WheelPos * 3);
serial.setValue(ch_offset++, 0);
Expand All @@ -637,7 +639,7 @@ void loop() {
serial.setValue(ch_offset++,255 - WheelPos * 3);
serial.setValue(ch_offset, 0);
}
#endif
#endif
}
} else {
testing.step = 0;
Expand All @@ -648,6 +650,7 @@ void loop() {
}
}


/* Streaming refresh */
#if defined(ESPS_MODE_PIXEL)
if (pixels.canRefresh())
Expand Down
6 changes: 4 additions & 2 deletions README.md
Expand Up @@ -9,14 +9,15 @@ Since this project began, the firmware has moved beyond just pixel support for t
Requirements
------------
Along with the Arduino IDE, you'll need the following software to build this project:
- [Adruino for ESP8266](https://github.com/esp8266/Arduino) - Arduino core for ESP8266
- [Adruino for ESP8266](https://github.com/esp8266/Arduino) - Arduino core for ESP8266 **2.40-rc1 or greater required**
- [Arduino ESP8266 Filesystem Uploader](https://github.com/esp8266/arduino-esp8266fs-plugin) - Arduino plugin for uploading files to SPIFFS
- [gulp](http://gulpjs.com/) - Build system to process web sources. Optional, but recommended. Refer to the html [README](html/README.md) for more information.

The following libraries are required:
- [E131](https://github.com/forkineye/E131) - E1.31 (sACN) Library for Arduino
- [ArduinoJson](https://github.com/bblanchon/ArduinoJson) - Arduino JSON Library
- [ESPAsyncTCP](https://github.com/me-no-dev/ESPAsyncTCP) - Asynchronous TCP Library
- [ESPAsyncUDP](https://github.com/me-no-dev/ESPAsyncUDP) - Asynchronous UDP LibraryA
- [ESPAsyncWebServer](https://github.com/me-no-dev/ESPAsyncWebServer) - Asynchronous Web Server Library

Important Notes on Compiling and Flashing
Expand Down Expand Up @@ -45,6 +46,7 @@ Resources

Credits
-------
- The people at http://diychristmas.org and http://doityourselfchristmas.com for inspiration.
- The great people at http://diychristmas.org and http://doityourselfchristmas.com for inspiration and support.
- Bill Porter for initial Renard and SoftAP aupport.
- Bill Porter and Grayson Lough for initial DMX support.
- Rich Danby for helping polish the front-end.
2 changes: 1 addition & 1 deletion SerialDriver.h
Expand Up @@ -29,7 +29,7 @@ GNU General Public License for more details.
#include "HardwareSerial.h"

/* UART for Renard / DMX output */
#define SEROUT_UART 0
#define SEROUT_UART 1

#if SEROUT_UART == 0
#define SEROUT_PORT Serial
Expand Down
6 changes: 4 additions & 2 deletions gulpfile.js
Expand Up @@ -23,17 +23,19 @@ gulp.task('html', function() {

/* CSS Task */
gulp.task('css', function() {
return gulp.src(['html/**/*.css'])
return gulp.src(['html/css/bootstrap.css', 'html/style.css'])
.pipe(plumber())
.pipe(concat('esps.css'))
.pipe(cleancss())
.pipe(gzip())
.pipe(gulp.dest('data/www'));
});

/* JavaScript Task */
gulp.task('js', function() {
return gulp.src(['html/**/*.js'])
return gulp.src(['html/js/jquery*.js', 'html/js/bootstrap.js', 'html/js/jqColorPicker.js', 'html/script.js'])
.pipe(plumber())
.pipe(concat('esps.js'))
.pipe(uglifyjs())
.pipe(gzip())
.pipe(gulp.dest('data/www'));
Expand Down
14 changes: 5 additions & 9 deletions html/index.html
Expand Up @@ -5,8 +5,7 @@
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title id="title"></title>
<link rel="stylesheet" type="text/css" href="css/bootstrap.css">
<link rel="stylesheet" type="text/css" href="style.css">
<link rel="stylesheet" type="text/css" href="esps.css">
</head>

<body>
Expand Down Expand Up @@ -82,9 +81,9 @@
<label class="control-label col-sm-2" for="password">Password</label>
<div class="col-sm-10"><input type="text" class="form-control" id="password" name="password" placeholder="Enter Password"></div>
</div>
<div class="form-group">
<div class="form-group" id="fg_hostname">
<label class="control-label col-sm-2" for="hostname">Hostname</label>
<div class="col-sm-10"><input type="text" class="form-control" id="hostname" name="hostname" placeholder="Enter Hostname"></div>
<div class="col-sm-10"><input type="text" class="form-control has-error" id="hostname" name="hostname" placeholder="Enter Hostname"></div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
Expand All @@ -110,7 +109,7 @@
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button type="button" onclick="submitWiFi()" class="btn btn-primary">Save Changes</button>
<button id="btn_wifi" type="button" onclick="submitWiFi()" class="btn btn-primary" disabled>Save Changes</button>
</div>
</div>
</form>
Expand Down Expand Up @@ -362,10 +361,7 @@ <h4 class="modal-title">WebSocket Error</h4>
</div>
</footer>

<script type="text/javascript" src="js/jquery-3.1.1.js"></script>
<script type="text/javascript" src="js/bootstrap.js"></script>
<script type="text/javascript" src="js/jqColorPicker.js"></script>
<script type="text/javascript" src="script.js"></script>
<script type="text/javascript" src="esps.js"></script>

<script>
wsConnect();
Expand Down
20 changes: 17 additions & 3 deletions html/script.js
Expand Up @@ -26,13 +26,13 @@ $(function() {
$('#update').modal({backdrop: 'static', keyboard: false});
});

/* Test mode toggles */
// Test mode toggles
$('#tmode').change(function() {
$('.tdiv').addClass('hidden');
$('#'+$('select[name=tmode]').val()).removeClass('hidden');
});

/* Color Picker */
// Color Picker
$('.color').colorPicker({
buildCallback: function($elm) {
var colorInstance = this.color;
Expand Down Expand Up @@ -123,6 +123,21 @@ $(function() {
$('#s_baud').prop('disabled', false);
});

// Hostname Validation
$('#hostname').keyup(function() {
var re = /^([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])$/;
if (re.test($(this).val())) {
$('#fg_hostname').removeClass('has-error');
$('#fg_hostname').addClass('has-success');
$('#btn_wifi').prop('disabled', false);
} else {
$('#fg_hostname').removeClass('has-success');
$('#fg_hostname').addClass('has-error');
$('#btn_wifi').prop('disabled', true);
}
});


canvas = document.getElementById("canvas");
ctx = canvas.getContext("2d");
ctx.font = "20px Arial";
Expand Down Expand Up @@ -547,7 +562,6 @@ function test() {
}
}


function showReboot() {
$('#update').modal('hide');
$('#reboot').modal({backdrop: 'static', keyboard: false});
Expand Down
1 change: 0 additions & 1 deletion wshandler.h
Expand Up @@ -50,7 +50,6 @@ void procX(uint8_t *data, AsyncWebSocketClient *client) {
uint32_t seqErrors = 0;
for (int i = 0; i < ((uniLast + 1) - config.universe); i++)
seqErrors =+ seqError[i];

client->text("X2" + (String)config.universe + ":" +
(String)uniLast + ":" +
(String)e131.stats.num_packets + ":" +
Expand Down

0 comments on commit 85c3b4f

Please sign in to comment.