[SOLVED] Red LED Flashing When Using TCPClient

I’m trying to use a push button to send a REST GET command using TCPClient. I’m able to successfully send the GET command, but the Core keeps flashing a red SOS and then eleven(11) red blinks before it reboots. This is happening very time I hit my push button. According to the Troubleshooting Docs, 11 red blinks means Invalid Case. What exactly does this mean and how do I fix it?

    const int buttonPin = D0;
    
    long lastDebounceTime = 0;
    const long debounceDelay = 5000;
    
    byte server[] = { 192, 168, 1, 150 };
    
    TCPClient client;
    
    void setup()
    {
      pinMode(buttonPin, INPUT);
      Serial.begin(9600);
      attachInterrupt(buttonPin, print, RISING);
      Time.zone(-8);
    };
    
    void loop(){};
    
    void print()
    {
      unsigned long m = millis();
      if (m - lastDebounceTime > debounceDelay)
        {
          sendData();
        }
      lastDebounceTime = m;
    }
    
    void sendData()
    {
        delay(1000);
        
        if (client.connect(server, 8080)){
            Serial.println("Connection successful");
            client.println("GET /controller/rest/control/195/50 HTTP/1.1");
            client.println("Host: 192.168.1.150");
            client.println("Content-Length: 0");
            client.println("Connection: close");
            client.println();
        }
        else{
            Serial.println("Connection failed");
            client.stop();
        }
        Serial.println("End");
    };

Thanks in advance.


Update

I’ve implemented @peekay123 clickButton library and all seems to be working. I think it was blinking red because I was doing too much in the interrupt method. I’ve also posted it on GitHub.

/*
    Title:          openremote-spark-button
    Description:    Update a OpenRemote slider using a Spark Core with a pushbutton
    Author:         Nicholas Wilde <ncwilde43@gmail.com>
    Date:           06/11/2014
    
    Note:           This example is based off of pkourany's clickButton demo
                    <https://github.com/pkourany/clickButton/blob/master/firmware/examples/clickButtonDemo.cpp>
*/

// This #include statement was automatically added by the Spark IDE.
#include "clickButton/clickButton.h"

// Values
const unsigned int sliderVal = 50; // The value we want to set the slider to.
const unsigned int sliderId = 195; // The ID of the OpenRemote slider.

// the Button
const int buttonPin1 = 0;
ClickButton button1(buttonPin1);

// Button results 
int function = 0;

// TCPClient stuff.
TCPClient client;

// This routine runs only once upon reset
void setup()
{
    Serial.begin(9600);
    pinMode(D0, INPUT);

    // Setup button timers (all in milliseconds / ms)
    // (These are default if not set, but changeable for convenience)
    button1.debounceTime   = 20;   // Debounce timer in ms
    button1.multiclickTime = 250;  // Time limit for multi clicks
    button1.longClickTime  = 1000; // time until "held-down clicks" register
}

// This routine loops forever
void loop()
{
    // Update button state
    button1.Update();

    // Save click codes in LEDfunction, as click codes are reset at next Update()
    if (button1.clicks != 0) function = button1.clicks;

    if(function == -1) //Long click
    {
        Serial.println("SINGLE LONG click");
        sendData();
    }
    function = 0;
    delay(5);
}

// Send a GET request using TCPClient
void sendData()
{
    delay(1000);
    Serial.println("Connecting to server ...");
    if (client.connect("192.168.1.150", 8080)) // IP & port of local OpenRemote server
    {
        Serial.println("Connection successful");
        String restString = buildString(sliderId, sliderVal);
        
        client.println(restString);
        client.println("Host: 192.168.1.150");
        client.println("Content-Length: 0");
        client.println();
    }
    else Serial.println("Connection failed");
    delay(2000); // Delay needed to allow the GET command to be received.
    client.stop();
}

// Build the GET string with the given parameters
String buildString(int id, int val)
{
    String s = "GET /controller/rest/control/";
    s += id;
    s += "/";
    s += val;
    s += " HTTP/1.1";
    Serial.println(s);
    return s;
}

client.stop() needs to be called for every client.connect() else you’ll run out of memory. Or the max no of concurrent connections. Move it to the then clause. I guess this might not be the only problem if the sketch is barfing on the 1st button press. Why is the loop() function empty?

I think you might not want, in this case, to call the interrupt service routine on RISING but on HIGH.

Also while an interrupt service routine is being run there are lots of things you cannot do - and one of these is to call millis(). Best to only set a volatile and global variable there and then test that in loop(), calling sendData() from there.

I would recommend reading http://docs.spark.io/firmware/#other-functions-interrupts

2 Likes

@NickW, @psb777 is totally correct. Interrupt service routines need to be “lite” and calling sendData() is not. To avoid interrupt servicing altogether, you could use the clickButton() library in the web IDE as part of loop(). It is also here if you use local compiling. :smiley:

@peekay123 & @psb777, thank you for your quick replies. I’ll implement your suggestions and let you know how it works out.

@peekay123, I’m trying to compile your clickButton example, but I keep getting the following errors. The only thing I changed was the #include clickButton/clickButton.h.

In file included from ../inc/spark_wiring.h:30:0,
from ../inc/application.h:31,
from /button2.cpp:2:
../../core-common-lib/SPARK_Firmware_Driver/inc/config.h:12:2: warning: #warning "Defaulting to Release Build" [-Wcpp]
In file included from /clickButton/clickButton.cpp:52:0:
/clickButton/clickButton.h:59:25: error: expected ')' before 'buttonPin'
/clickButton/clickButton.h:60:25: error: expected ')' before 'buttonPin'
/clickButton/clickButton.h:61:25: error: expected ')' before 'buttonPin'
/clickButton/clickButton.h:64:5: error: 'boolean' does not name a type
/clickButton/clickButton.h:69:5: error: 'uint8_t' does not name a type
/clickButton/clickButton.h:70:5: error: 'boolean' does not name a type
/clickButton/clickButton.h:71:5: error: 'boolean' does not name a type
/clickButton/clickButton.h:72:5: error: 'boolean' does not name a type
/clickButton/clickButton.cpp:54:25: error: expected constructor, destructor, or type conversion before '(' token
/clickButton/clickButton.cpp:71:25: error: expected constructor, destructor, or type conversion before '(' token
/clickButton/clickButton.cpp:87:25: error: expected constructor, destructor, or type conversion before '(' token    
/clickButton/clickButton.cpp: In member function 'void ClickButton::Update()':
/clickButton/clickButton.cpp:112:27: error: 'millis' was not declared in this scope
/clickButton/clickButton.cpp:113:3: error: '_btnState' was not declared in this scope

@NickW, I may have forgotten to put #include “application.h” at the top of clickButton.h !!! Just add it and it should work. :open_mouth:

UPDATE: I updated the library on the web IDE

@peekay123, your example now works. I’ll rewrite my TCPClient sketch using the library and I’ll let you know about my results. Thanks again.

1 Like