0

I've created a homebridge server on a Raspberry Pi Zero and have configured it to use my NodeMCU v1 (Esp - 12E Module) as an accessory to control RGB strip lights.

All works normally until you don't use the home kit to control the lights for certain amount of time (~30 seconds). My iPhone says that the accessory is non responsive until I force a command to happen, this after some time activates the accessory and goes back to normal.

Is there a way of keeping the NodeMCU active to HTTP responses all the time?

The code I have used is a mashup of a tutorial I used but I've modified it with some more features. (All coded in Arduino)

//NodeMCU RGB-Controller for Homebridge & HomeKit (Siri)
#include <ESP8266WiFi.h>
#include <math.h>
#define redPin 13 //D7 - Red channel
#define grnPin 12 //D6 - Green channel
#define bluPin 14 //D5 - Blue channel
#define white 5 //D1 - Blue channel
WiFiServer server(80); //Set server port
String readString; //String to hold incoming request
String hexString = "000000"; //Define inititial color here (hex value), 080100 would be a calm warmtone i.e.
int state;
int r;
int g;
int b;
float R;
float G;
float B;
int x;
int V;
///// WiFi SETTINGS - Replace with your values /////////////////
const char* ssid = "xxxxxxx";
const char* password = "xxxxxxx";
IPAddress ip(192,168,1,234); // set a fixed IP for the NodeMCU
IPAddress gateway(192,168,1,1); // Your router IP
IPAddress subnet(255,255,255,0); // Subnet mask
////////////////////////////////////////////////////////////////////
void WiFiStart() { 
 Serial.print("Connecting to ");
 Serial.println(ssid);
 WiFi.begin(ssid, password);
 WiFi.config(ip, gateway, subnet); //Set a fixed IP. You can comment this out and set it in your router instead.
 while (WiFi.status() != WL_CONNECTED) {
 delay(100);
 Serial.print("_");
 }
 Serial.println();
 Serial.println("Done");
 Serial.print("IP address: ");
 Serial.println(WiFi.localIP());
 Serial.println("");
 server.begin(); 
}
void allOff() {
 state = 0;
 analogWrite(redPin, 0);
 analogWrite(grnPin, 0);
 analogWrite(bluPin, 0);
}
//Write requested hex-color to the pins (10bit pwm)
void setHex() {
 state = 1;
 long number = (long) strtol( &hexString[0], NULL, 16);
 r = number >> 16;
 g = number >> 8 & 0xFF;
 b = number & 0xFF;
 r = map(r, 0, 255, 0, 1023); //added for 10bit pwm
 g = map(g, 0, 255, 0, 1023); //added for 10bit pwm
 b = map(b, 0, 255, 0, 1023); //added for 10bit pwm
 analogWrite(redPin, (r));
 analogWrite(grnPin, (g));
 analogWrite(bluPin, (b));
}
//Compute current brightness value
//For serial debugging only
void showValues() {
 Serial.print("Status on/off: ");
 Serial.println(state);
 Serial.print("RGB color: ");
 Serial.print(r);
 Serial.print(".");
 Serial.print(g);
 Serial.print(".");
 Serial.println(b);
 Serial.print("Hex color: ");
 Serial.println(hexString);
 Serial.print("Brightness: ");
 Serial.println(V);
 Serial.println("");
}
void setup(){
 Serial.begin(9600);
 delay(1);
 pinMode(redPin, OUTPUT); //declaration added
 pinMode(grnPin, OUTPUT); //declaration added
 pinMode(bluPin, OUTPUT); //declaration added
 setHex(); //Set initial color after booting. Value defined above
 WiFi.mode(WIFI_STA);
 WiFiStart();
 //showValues(); //Uncomment for serial output
}
void loop() {
 //Reconnect on lost WiFi connection (superfluous - will reconnect anyway)
 if (WiFi.status() != WL_CONNECTED) {
 WiFiStart();
 }
 WiFiClient client = server.available();
 if (!client) {
 return;
 }
 while(client.connected() && !client.available()) {
 delay(1);
 }
 //Respond on certain Homebridge HTTP requests
 if (client) {
 while (client.connected()) {
 if (client.available()) {
 char c = client.read();
 if (readString.length() < 100) {
 readString += c;
 } 
 if (c == '\n') {
 Serial.print("Request: "); //Uncomment for serial output 
 Serial.println(readString); //Uncomment for serial output
 //Send reponse
 client.println("HTTP/1.1 200 OK"); 
 client.println("Content-Type: text/html");
 client.println();
 //On
 if(readString.indexOf("on") >0) {
 setHex();
 Serial.println("on");
 showValues();
 }
 if(readString.indexOf("xw") >0) {
 Serial.println("won");
 analogWrite(white, 1024);
 }
 if(readString.indexOf("yw") >0) {
 Serial.println("woff");
 analogWrite(white, 0);
 }
 //Off
 if(readString.indexOf("off") >0) {
 allOff();
 showValues();
 }
 //Set color
 if(readString.indexOf("set") >0) {
 hexString = "";
 hexString = (readString.substring(9,15));
 setHex();
 //showValues();
 }
 //Status on/off
 if(readString.indexOf("status") >0) {
 client.println(state);
 }
 //Status color (hex)
 if(readString.indexOf("color") >0) {
 client.println(hexString);
 }
 //Status brightness (%)
 if(readString.indexOf("bright") >0) {
 client.println(V);
 }
 delay(1);
 client.stop();
 readString="";
 }
 }
 }
 }
}
Majenko
106k5 gold badges81 silver badges139 bronze badges
asked Dec 19, 2017 at 19:09

1 Answer 1

2

You are probably running out of RAM because you are using the String object instead of a fixed-size char[] buffer. This code, in particular:

if (readString.length() < 100) {
 readString += c;
} 

Concatenating String objects using the overloaded plus operator allocates a whole new block of RAM for the new, longer string. It frees the previous memory, but since you keep adding one character at a time, new strings won't be able to be put into the once-used RAM.

You should instead use C-style strings (character arrays) and the standard functions for managing them, such as strnlen() and strncat(), etc. Note, I am suggesting the versions of string functions with a maxlen parameter, which helps avoid bugs due to unterminated strings.

answered Dec 19, 2017 at 19:19
3
  • I can't seem to implement this Commented Dec 27, 2017 at 16:20
  • Share what you’ve tried. Thus page has a good overview gammon.com.au/concat Commented Dec 27, 2017 at 20:48
  • I had to make a new question as the comment wouldn't let me copy all my changed code: arduino.stackexchange.com/questions/48066/… Commented Jan 5, 2018 at 16:39

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.