Feather HUZZAH ESP8266 Mesh Network Dropouts/Callback Hangs
Posted: Wed Jul 05, 2017 10:25 am
I'm in a world of hurt and don't know how to get out of it.
I've built a set for a theatre production of Newsies, which consists of three two-story towers. Each of six total openings in the towers have servo driven, Feather Huzzah controlled projection screens that move up and down independently throughout the show. They are also battery powered, since the towers have to move around the stage.
Our show opens tonight, and nothing is working reliably. Yesterday morning, I got all six screens to work, but then at last nights tech rehearsal, I had connection dropouts and occasional repetitive blasts of Serial transmissions from what appears to be one of the chips stuck in the message received callback, which fires off the Serial.print call "Start Here: Message received from..." over and over. I'm using the "Painless Mesh" library from BlackEdder: https://gitlab.com/BlackEdder/painlessMesh/tree/master
I've tried everything mentioned all over the interwebs that I can find - yield();, setting the watchdog to 8 seconds, adding a 1000uf cap on the battery input. The boards were REALLY wonky before adding the yield(); I instead had ESP.wdtfeed - when I added yield(); the boards flipped out, but when I removed the wdtfeed and kept yield, they all worked fairly well. But there are still too many hiccups to feel comfortable running them for the show with an audience.
I am controlling the AP with Touchdesigner, a video production software that has integrated serial out communication. The Touchdesigner side of things works just fine. The code below is what's on the AP, and then one of the six that's on the nodes. The only difference in the code on the nodes is the value used to stop the continuous servo andwhich char to read from the packet sent to all Nodes from the AP. For example, 111111 means all screens up, 000000, all down, 111000, the first three up and last three down, etc. 333333 and 444444 is for my IR tracking LEDs relay triggering. I haven't got to that part yet.
I know this is long, but I'm begging for any help at this point - like I said, show opens tonight, and I'm at work all day =(
AP Code:
Node 1 Code:
ANY Advice is appreciated. Let me know if any of the code (which I never commented) doesn't make sense. Thanks!
I've built a set for a theatre production of Newsies, which consists of three two-story towers. Each of six total openings in the towers have servo driven, Feather Huzzah controlled projection screens that move up and down independently throughout the show. They are also battery powered, since the towers have to move around the stage.
Our show opens tonight, and nothing is working reliably. Yesterday morning, I got all six screens to work, but then at last nights tech rehearsal, I had connection dropouts and occasional repetitive blasts of Serial transmissions from what appears to be one of the chips stuck in the message received callback, which fires off the Serial.print call "Start Here: Message received from..." over and over. I'm using the "Painless Mesh" library from BlackEdder: https://gitlab.com/BlackEdder/painlessMesh/tree/master
I've tried everything mentioned all over the interwebs that I can find - yield();, setting the watchdog to 8 seconds, adding a 1000uf cap on the battery input. The boards were REALLY wonky before adding the yield(); I instead had ESP.wdtfeed - when I added yield(); the boards flipped out, but when I removed the wdtfeed and kept yield, they all worked fairly well. But there are still too many hiccups to feel comfortable running them for the show with an audience.
I am controlling the AP with Touchdesigner, a video production software that has integrated serial out communication. The Touchdesigner side of things works just fine. The code below is what's on the AP, and then one of the six that's on the nodes. The only difference in the code on the nodes is the value used to stop the continuous servo andwhich char to read from the packet sent to all Nodes from the AP. For example, 111111 means all screens up, 000000, all down, 111000, the first three up and last three down, etc. 333333 and 444444 is for my IR tracking LEDs relay triggering. I haven't got to that part yet.
I know this is long, but I'm begging for any help at this point - like I said, show opens tonight, and I'm at work all day =(
AP Code:
Code: Select all
#include <painlessMesh.h>
#include <painlessMeshSTA.h>
#include <painlessMeshSync.h>
#include <painlessScheduler.h>
#include <SimpleList.h>
painlessMesh mesh;
bool calc_delay = false;
SimpleList<uint32_t> nodes;
//Servo Identifiers
#define SERVO_TOP_LEFT 15774220 //350 STOP NEEDS REVISITED
#define SERVO_TOP_CENTER 15711956 //343 STOP
#define SERVO_TOP_RIGHT 15772684 //353 STOP
#define SERVO_BOTTOM_LEFT 15710311 //346 STOP
#define SERVO_BOTTOM_CENTER 15712451 //353 STOP
#define SERVO_BOTTOM_RIGHT 15773974 //360 STOP
int incomingByte = 0; // for incoming serial data
String incomingPackage = "";
String package = "";
String msg = "";
uint32_t dest;
//#include <easyMesh.h>
#include <string>
// some gpio pin that is connected to an LED...
// on my rig, this is 5, change to the right number of your LED.
#define LED 0 // GPIO number of connected LED
#define BLINK_PERIOD 1000000 // microseconds until cycle repeat
#define BLINK_DURATION 100000 // microseconds LED is on for
#define MESH_SSID "newsies"
#define MESH_PASSWORD "dreamers"
#define MESH_PORT 5555
//easyMesh mesh;
uint32_t sendMessageTime = 0;
void setup() {
Serial.begin(115200);
pinMode( LED, OUTPUT );
//mesh.setDebugMsgTypes( ERROR | MESH_STATUS | CONNECTION | SYNC | COMMUNICATION | GENERAL | MSG_TYPES | REMOTE ); // all types on
mesh.setDebugMsgTypes( ERROR | STARTUP ); // set before init() so that you can see startup messages
mesh.init(MESH_SSID, MESH_PASSWORD, MESH_PORT);
mesh.onReceive(&receivedCallback);
mesh.onNewConnection(&newConnectionCallback);
mesh.onChangedConnections(&changedConnectionCallback);
mesh.onNodeTimeAdjusted(&nodeTimeAdjustedCallback);
mesh.onNodeDelayReceived(&delayReceivedCallback);
//mesh.scheduler.addTask( taskSendMessage );
//taskSendMessage.enable() ;
randomSeed(analogRead(A0));
}
void loop() {
mesh.update();
if (Serial.available() > 0) {
// read the incoming byte:
incomingPackage = Serial.readStringUntil('\n');
Serial.print(incomingPackage);
yield();
mesh.sendBroadcast(incomingPackage);
}
}
void receivedCallback( uint32_t from, String &msg ) {
Serial.printf("startHere: Received from %d msg=%s\n", from, msg.c_str());
}
void newConnectionCallback( uint32_t nodeId ) {
Serial.printf("startHere: New Connection, nodeId = %u\n", nodeId);
}
void changedConnectionCallback() {
Serial.printf("Changed connections %s\n", mesh.subConnectionJson().c_str());
nodes = mesh.getNodeList();
Serial.printf("Num nodes: %d\n", nodes.size());
Serial.printf("Connection list:");
SimpleList<uint32_t>::iterator node = nodes.begin();
while (node != nodes.end()) {
Serial.printf(" %u", *node);
node++;
}
Serial.println();
calc_delay = true;
}
void nodeTimeAdjustedCallback(int32_t offset) {
Serial.printf("Adjusted time %u. Offset = %d\n", mesh.getNodeTime(), offset);
}
void delayReceivedCallback(uint32_t from, int32_t delay) {
Serial.printf("Delay to node %u is %d us\n", from, delay);
}
Node 1 Code:
Code: Select all
#include <painlessMesh.h>
#include <painlessMeshSTA.h>
#include <painlessMeshSync.h>
#include <painlessScheduler.h>
#include <SimpleList.h>
painlessMesh mesh;
bool calc_delay = false;
SimpleList<uint32_t> nodes;
#include <Adafruit_PWMServoDriver.h>
//#include <easyMesh.h>
Adafruit_PWMServoDriver servo = Adafruit_PWMServoDriver();
// some gpio pin that is connected to an LED...
// on my rig, this is 5, change to the right number of your LED.
#define LED 0 // GPIO number of connected LED
#define TOPIR 13 // GPIO Pin for Top IR Interrupt Receiver
#define BOTTOMIR 12 // GPIO Pin for Bottom IR Interrupt Receiver
#define RELAY 16 //Solid State Relay to Control the IR Emitters
//Servo Directional Speeds
//Down is lower than 350 @60Hz
//Up is Higher than 350 @60Hz
#define UP 500
#define DOWN 200
#define STOP 350
#define MESH_SSID "newsies"
#define MESH_PASSWORD "dreamers"
#define MESH_PORT 5555
//easyMesh mesh;
String package = "";
uint32_t sendMessageTime = 0;
void setup() {
Serial.begin(115200);
servo.begin();
delay(10);
servo.setPWMFreq(60); // Analog servos run at ~60 Hz updates
pinMode( LED, OUTPUT );
pinMode( TOPIR, INPUT_PULLUP );
pinMode( BOTTOMIR, INPUT_PULLUP );
pinMode( RELAY, OUTPUT );
ESP.wdtDisable();
ESP.wdtEnable(WDTO_8S);
mesh.setDebugMsgTypes( ERROR | MESH_STATUS | CONNECTION | SYNC | COMMUNICATION | GENERAL | MSG_TYPES | REMOTE ); // all types on
mesh.setDebugMsgTypes( ERROR | STARTUP ); // set before init() so that you can see startup messages
mesh.init(MESH_SSID, MESH_PASSWORD, MESH_PORT);
mesh.onReceive(&receivedCallback);
mesh.onNewConnection(&newConnectionCallback);
mesh.onChangedConnections(&changedConnectionCallback);
mesh.onNodeTimeAdjusted(&nodeTimeAdjustedCallback);
mesh.onNodeDelayReceived(&delayReceivedCallback);
Serial.print("This Node is: ");
Serial.println(ESP.getChipId());
}
//...........Periods are items to change............
void loop() {
mesh.update();
servo.setPWM(0, 0, 352); //This cannot be removed.....................
//Serial.println(package);
if (package != "") {
if (package.charAt(0) == '1')
{
yield();
while (digitalRead(TOPIR) == LOW)
{
yield();
servo.setPWM(0, 0, UP);
//ESP.wdtFeed();
}
delay(15);
package = "";
}
else if (package.charAt(0) == '0')
{
yield();
while (digitalRead(BOTTOMIR) == HIGH)
{
yield();
servo.setPWM(0, 0, DOWN);
//ESP.wdtFeed();
}
delay(15);
package = "";
}
else if (package.charAt(0) == '3')
{
digitalWrite(RELAY, LOW);
}
else if (package.charAt(0) == '4')
{
digitalWrite(RELAY, HIGH);
}
ESP.wdtFeed();
}
package == ""; //Resets Package Variable to Empty to Avoid Loop Trigger
}
void receivedCallback( uint32_t from, String &msg ) {
//Serial.printf("startHere: Received from %d msg=%s\n", from, msg.c_str());
package = msg.c_str();
}
void newConnectionCallback( uint32_t nodeId ) {
Serial.printf("startHere: New Connection, nodeId = %u\n", nodeId);
}
void changedConnectionCallback() {
Serial.printf("Changed connections %s\n", mesh.subConnectionJson().c_str());
nodes = mesh.getNodeList();
Serial.printf("Num nodes: %d\n", nodes.size());
Serial.printf("Connection list:");
SimpleList<uint32_t>::iterator node = nodes.begin();
while (node != nodes.end()) {
Serial.printf(" %u", *node);
node++;
}
Serial.println();
calc_delay = true;
}
void nodeTimeAdjustedCallback(int32_t offset) {
Serial.printf("Adjusted time %u. Offset = %d\n", mesh.getNodeTime(), offset);
}
void delayReceivedCallback(uint32_t from, int32_t delay) {
Serial.printf("Delay to node %u is %d us\n", from, delay);
}
ANY Advice is appreciated. Let me know if any of the code (which I never commented) doesn't make sense. Thanks!