Dear all,
I have a big issue with my core.
I am pretty new to the micro controller programming.
I have started my own project to control a LED strip via WLAN and an iPhone web app.
Some more background docu on the project to be found here: http://community.spark.io/t/very-simple-web-controlled-neopixel-led-strip/9893
I want to control the core via UDP from a PHP page (running on my Synology) as this is a straight forward setup and very responsive and doesn’t need iOS programming.
I have now created a firmware wich will register itself on the Server with its name and IP and sends a regular heart beat so that the server knows about the status.
But now going forward and adding functionality to the firmware I am facing issues with the firmware.
With the code attached the core will hang up after a couple of minutes and is not responding at all. It is just flashing cyan and just a hard reset helps.
Can anybody help? Is there something fundamental wrong in the coding:
// This #include statement was automatically added by the Spark IDE.
#include "neopixel/neopixel.h"
// This #include statement was automatically added by the Spark IDE.
#include "my_helpers.h"
//#################################################################
// BUGS to fix
//#################################################################
// 1. debug parameter isn't passed to the helpers class
// 2. Core starts blinkingt cyan after a while and isn't reacting anymore
//#################################################################
// GLOBAL DEFINITIONS
//#################################################################
// Define the LED strip parameters
#define PIXEL_COUNT 70 // Number of Pixels
#define PIXEL_PIN D0 // Pin of the data connection to the strip
#define PIXEL_TYPE TM1829 // Strip controller type
// Define the UDP parameters
const int UDP_TX_PACKET_MAX_SIZE=860; //UDP package size
const unsigned int localPort = 8888; //UDP Port used for two way communication
// Define the TCP call back parameters
char home_server[] = "diskstation"; // diskstation
const int home_server_port = 80; // diskstation
const String name_device = "test"; // name of the spark core in the home automation system
const int beat_rate = 10000; // heart beat rate sent to server in ms
// Switch debugging on/off
const int debug = 1;
//#################################################################
// Needed Objects
//#################################################################
// An UDP instance to let us send and receive packets over UDP
UDP Udp;
// An TCP client instance to let us send and receive packets over TCP
TCPClient TCP_client;
// create some helping fuctions
my_helpers h = my_helpers(debug);
// construct the strip object
Adafruit_NeoPixel strip = Adafruit_NeoPixel(PIXEL_COUNT, PIXEL_PIN, PIXEL_TYPE);
char packetBuffer[UDP_TX_PACKET_MAX_SIZE]; //buffer to hold incoming packet,
//#################################################################
// PROGRAM LOGIC
//#################################################################
void setup() {
// start the UDP
Udp.begin(localPort);
// Print your device IP Address via serial for debuging
if (debug == 1){Serial.begin(9600);}
if (debug == 1){delay (4000);}
if (debug == 1){Serial.println(WiFi.localIP());}
//Setup the strip & initialize all pixels to 'off'
strip.begin();
strip.show();
}
void loop() {
int packetSize = Udp.parsePacket();
if(packetSize)
{
if (debug == 1){Serial.print("Received packet of size ");}
if (debug == 1){Serial.println(packetSize);}
if (debug == 1){Serial.print("From ");}
IPAddress remote = Udp.remoteIP();
int port = Udp.remotePort();
if (debug == 1)
{
for (int i =0; i < 4; i++)
{
Serial.print(remote[i], DEC);
if (i < 3)
{
Serial.print(".");
}
}
}
if (debug == 1){Serial.print(", port ");}
if (debug == 1){Serial.println(port);}
// read the packet into packetBufffer
Udp.read(packetBuffer,UDP_TX_PACKET_MAX_SIZE);
if (debug == 1){Serial.println("Contents:");}
if (debug == 1){Serial.println(packetBuffer);}
String datagram = String(packetBuffer);
String command = h.dispatcher (datagram);
if (debug == 1){Serial.print("Command: ");}
if (debug == 1){Serial.println(command);}
String data = h.data_load (datagram);
if (debug == 1){Serial.print("Data: ");}
if (debug == 1){Serial.println(data);}
if (command == "ColorWipe")
{
int RGBValues[3];
h.RGBFromString(RGBValues, data);
colorWipe(strip.Color(RGBValues[0], RGBValues[1], RGBValues[2]), 300);
}
else if (command == "ColorAll")
{
int RGBValues[3];
h.RGBFromString(RGBValues, data);
colorAll(strip.Color(RGBValues[0], RGBValues[1], RGBValues[2]), 0);
}
else if (command == "Pixel") // not yet fully implemented
{
int RGBValues[3];
h.RGBFromString(RGBValues, data);
strip.setPixelColor(10, strip.Color(RGBValues[0], RGBValues[1], RGBValues[2]));
strip.show();
}
//echo back the UDP message
Udp.beginPacket(remote, port);
Udp.write(packetBuffer);
Udp.endPacket();
}
h.heart_beat(TCP_client, home_server, home_server_port, name_device, beat_rate);
} //end loop
//#################################################################
// LED Strip Functions (to be implemented in the helpers later)
//#################################################################
// Set all pixels in the strip to a solid color, then wait (ms)
void colorAll(uint32_t c, uint8_t wait) {
uint16_t i;
for(i=0; i<strip.numPixels(); i++) {
strip.setPixelColor(i, c);
}
strip.show();
delay(wait);
}
// Fill the dots one after the other with a color, wait (ms) after each one
void colorWipe(uint32_t c, uint8_t wait) {
for(uint16_t i=0; i<strip.numPixels(); i++) {
strip.setPixelColor(i, c);
strip.show();
delay(wait);
}
}
void rainbow(uint8_t wait) {
uint16_t i, j;
for(j=0; j<256; j++) {
for(i=0; i<strip.numPixels(); i++) {
strip.setPixelColor(i, Wheel((i+j) & 255));
}
strip.show();
delay(wait);
}
}
// Slightly different, this makes the rainbow equally distributed throughout, then wait (ms)
void rainbowCycle(uint8_t wait) {
uint16_t i, j;
for(j=0; j<256; j++) { // 1 cycle of all colors on wheel
for(i=0; i< strip.numPixels(); i++) {
strip.setPixelColor(i, Wheel(((i * 256 / strip.numPixels()) + j) & 255));
}
strip.show();
delay(wait);
}
}
// Input a value 0 to 255 to get a color value.
// The colours are a transition r - g - b - back to r.
uint32_t Wheel(byte WheelPos) {
if(WheelPos < 85) {
return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
} else if(WheelPos < 170) {
WheelPos -= 85;
return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3);
} else {
WheelPos -= 170;
return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3);
}
}
The Includes
/*-------------------------------------------------------------------------
-------------------------------------------------------------------------*/
#include "my_helpers.h"
#include "neopixel/neopixel.h"
//constructor
my_helpers::my_helpers(int debug_flag) {
int debug = 1;
int request_sent = 0;
unsigned long time_stamp = 0;
}
//sends a heart beat to the server together with the IP address & device name
void my_helpers::heart_beat(TCPClient client, char host[], int port, String my_name, int heart_rate)
{
int debug = 1;
if (time_stamp < millis() && request_sent == 0)
{
if (debug == 1){Serial.println("trying to connect to:");}
if (debug == 1){Serial.print(host);}
if (debug == 1){Serial.print(":");}
if (debug == 1){Serial.print(port);}
if (client.connect(host, port))
{
if (debug == 1){Serial.println(" connected");}
// send the heart beat
client.print("GET /led_strip/controller.php?function=heartbeat&device=");
client.print(my_name);
client.print("&IP=");
client.print(WiFi.localIP());
client.println(" HTTP/1.0");
client.println("Host: diskstation");
client.println("Content-Length: 0");
client.println();
request_sent = 1;
if (debug == 1){Serial.println("request sent");}
time_stamp = millis() + heart_rate;
if (debug == 1){Serial.println("timestamp:");}
if (debug == 1){Serial.println(time_stamp);}
}
else
{
if (debug == 1){Serial.println("connection failed");}
time_stamp = millis() + 2000;
if (debug == 1){Serial.println("timestamp:");}
if (debug == 1){Serial.println(time_stamp);}
}
}
while (request_sent == 1)
{
if (client.available())
{
char c = client.read();
if (debug == 1){Serial.print(c);}
}
if (!client.connected())
{
if (debug == 1){Serial.println();}
if (debug == 1){Serial.println("disconnecting.");}
request_sent = 0;
client.stop();
}
}
}
//parse the two digit function number from the UDP datagram and return the function name
String my_helpers::dispatcher (String data)
{
switch (data.substring(0,2).toInt())
{
case 1:
return "ColorWipe";
break;
case 2:
return "ColorAll";
break;
case 3:
return "Rainbow";
break;
case 4:
return "RainbowCycle";
break;
case 5:
return "FullFade";
break;
case 9:
return "Pixel";
break;
default:
return "error";
break;
}
}
//parse the data from the UDP datagram and retrun it
String my_helpers::data_load (String data)
{
return data.substring(2);
}
//parse the two digit function number from the UDP datagram and return the function name
String my_helpers::pixelnumber (String data)
{
return data.substring(0,3);
}
// Splitt the string rrrgggbbb into seperate varaibles
void my_helpers::RGBFromString(int RGBArray[], String RGBString) {
RGBArray[0] = RGBString.substring(0, 3).toInt();
RGBArray[1] = RGBString.substring(3, 3).toInt();
RGBArray[2] = RGBString.substring(6, 3).toInt();
}
#ifndef MY_HELPERS_H
#define MY_HELPERS_H
#include "application.h"
#include "neopixel/neopixel.h"
class my_helpers
{
public:
// Constructor: no args needed
my_helpers(int debug_flag);
String dispatcher (String data); //parse the two digit function number from the UDP datagram and return the function name
String data_load (String data); //parse the data from the UDP datagram and retrun it
String pixelnumber (String data);
void heart_beat (TCPClient client, char host[], int port, String my_name, int heart_rate); //sends a heart beat to the server together with the IP address & device name
void RGBFromString(int RGBArray[], String RGBString); //Extracts seperate RGB values from this String "RRRGGGBBB"
private:
int debug;
int request_sent;
unsigned long time_stamp;
};
#endif // HELPERS_H