LED on 'NET not working

Below is the code that loaded on core:

 // -----------------------------------
// Controlling LEDs over the Internet
// -----------------------------------

// name the pins
int led1 = D7;
int led2 = D1;

// This routine runs only once upon reset
void setup()
{
   //Register our Spark function here
   Spark.function("led", ledControl);

   // Configure the pins to be outputs
   pinMode(led1, OUTPUT);
   pinMode(led2, OUTPUT);

   // Initialize both the LEDs to be OFF
   digitalWrite(led1, HIGH);
   digitalWrite(led2, LOW);
}


// This routine loops forever 
void loop()
{
   // Nothing to do here
}


// This function gets called whenever there is a matching API request
// the command string format is l<led number>,<state>
// for example: l1,HIGH or l1,LOW
//              l2,HIGH or l2,LOW

int ledControl(String command)
{
   int state = 0;
   //find out the pin number and convert the ascii to integer
   int pinNumber = command.charAt(1) - '0';
   //Sanity check to see if the pin numbers are within limits
   if (pinNumber < 0 || pinNumber > 1) return -1;

   // find out the state of the led
   if(command.substring(3,7) == "HIGH") state = 1;
   else if(command.substring(3,6) == "LOW") state = 0;
   else return -1;

   // write to the appropriate pin
   digitalWrite(pinNumber, state);
   return 1;
}

This is the curl sytax that I am using to turn OFF led on D7 throu 'NET

curl - k "https://api.spark.io/v1/devices/xxxxxxxx/led -d access_token=xxxxxxxxxx-d params=l1,HIGH"

I have also tried http://jflasher.github.io/spark-helper/

It does not turn OFF the LED on D7. Why? HELP.

I think the description of the code in the docu is actually quite misleading here. Always handy to run through the code yourself, even if it’s written by people as good as the ones here - everyone can overlook things. And it will make you a better coder.

I am not an expert on arduino code, so apologies for any errors in the following.

Follow the code through, you’ll see that sending “l1,HIGH” to the cloud will run the function ledControl("l1,HIGH"). It isn’t running 'ledControl(“D7,HIGH”) as you are expecting.

According to the function declaration, command = "l1,HIGH".

So when the function gets to:

int pinNumber = command.charAt(1) - '0';

Here it takes the second character of command in command.charAt(1) (why the second if it says 1?) and sets the variable pinNumber to be that value (1). (EDIT: see ScruffR’s explanation below as to why subtracting ‘0’ then returns an integer).

Then it checks to see if pinNumber is either 0 or 1 (remember this for later!)

Then it checks to see if you have sent an appropriate command (high or low) - the documentation here states it is checking the state of the led, which it isn’t really.

Then it writes the state to the pinNumber (0 or 1) with digitalWrite(pinNumber, state)

So when you send the command l1, you’re expecting it to map that to the location of ‘led1’, and then set D7 to be high, but it’s actually not remapping anything, it’s just trying to set D1 to be high. What happens when you send l2 then? Nothing should happen, as it is caught by this line: if (pinNumber < 0 || pinNumber > 1) return -1;

So, you’re probably wondering, what is the purpose of the line led1 = D7 in that case?
It is used to configure the pins to be outputs in pinMode(led1, OUTPUT); Other than that, it isn’t used again.

You’re probably also wondering, why do I need to send l1 then, instead of f1, or k1, or etc. etc. The answer is, you don’t, any of those would work (tested and confirmed).

Now, remember, if you send the parameter “l7”, it still won’t work, because of the pinNumber catcher. You’ll have to edit the code yourself to get that working.

The miracle of subtracting ‘0’ of the character you obtained with command.charAt(1) lies in the fact that this char is nothing else than a byte (e.g. char ‘1’ is 0x31 or 49 decimal in ASCII) when you now subtract the byte value of ‘0’ (in ASCII 0x30 or DEC 48) you get the result of 1 as a number.
Since the digits ‘0’ through to ‘9’ are located in consecutive order you can do this calculation for any other digit, too.

You are initializing D7 as HIGH, which turns it ON.

You need to use the following to turn it OFF:
curl - k "https://api.spark.io/v1/devices/xxxxxxxx/led -d access_token=xxxxxxxxxx-d params=l7,HIGH"

Also you need to modify your code on this line like this to make it work for any of the digital outputs 0 - 7:
if (pinNumber < 0 || pinNumber > 7) return -1;

@ScruffR, thanks -makes sense. Is this superior to int(command.charAt(1)) ?

Thanks all for your input. That explanation was great from Andrew.

1 Like

@andrew: In this case the -‘0’ version should be quite a bit faster than int().
Since int() is a function that works for any data type and also supports multi digit numbers there will be a considerable amount of overhead that you don’t need in this case since you know what data type you are expecting and that you’ll only have to deal with a single digit.

Another “advantage” is that the -‘0’ is supported in standard C, where int() is not - the standard C pendant for converting multi digit strings to integer would by “atoi()” (ASCII to int).
But this only counts as advantage, when you came from C :wink:

1 Like

@ScruffR Thanks, that makes perfect sense. Never knew about string subtraction before.

1 Like

Hi!, i’m trying to do a similar code but only with the D7 pin, can you help me?

I’m trying to control the D7 pin LED from a website, I made this code but when I press the buttons the LED does not light :confused:

This is my spark core code:

int led1 = D7; 
            
void setup() {

  Spark.function("led", ledControl);
  
  pinMode(led1, OUTPUT);
  
  digitalWrite(led1, LOW);
}

void loop() {
   // Nothing to do here
}

int ledControl(String state){
    if(state=="HIGH"){
    digitalWrite(led1, HIGH);  // Turn ON the LED pins
    delay(500);
    }
    if(state=="LOW"){
    digitalWrite(led1, LOW);  // Turn OFF the LED pins
    delay(500);
    }
}

and this is my website code:


<!DOCTYPE HTML>
<html>
  <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js" type="text/javascript" charset="utf-8"></script>

 <body>
 <br><br>
 <button id="onbutton" onclick="states(1)">ON</button>
 <button id="offbutton" onclick="states(0)">OFF</button>

 <script type="text/javascript">
   var deviceID    = "0000000000000";  //example
   var accessToken = "11111111111111111111111111111"; //example
   var setFunc = "led";

   function states(value) {

    var newValue="";

    if(value==1){
    newValue=="HIGH";
    }
    else if(value==0){
    newValue=="LOW";
    }

    var requestURL = "https://api.spark.io/v1/devices/" +deviceID + "/" + setFunc + "/";
    $.post( requestURL, { params: newValue, access_token: accessToken });

   }


  </script>
 </body>
</html>

Thank you for your help!! :grin:

1 Like

I can have a look into this for you, but you could also try some things.

You could find out if the problem is more on the Core or on the remote side.
Whether the Spark.function() gets triggered or not or if it’s only that neither if statement catches.
You could try some other means of triggering the Spark.function() (e.g. Spark Dev, curl, …).
You could have a closer look at the exact format of your requestURL.

And for the sake of readability, could you reformat your code the way it’s outlined in this thread?
And if you posted your web code as code rather than image, it would be easier for people to try your code out, without the need to type it off.

yeah, sorry for the ignorance, I did not know how to do that, thanks for the advice.

Is there an error message in the console? If so, could you post that?

I got the same behaviour and get this response

POST https://api.spark.io/v1/devices/<<deviceID>>/led 401 (Unauthorized)    jquery.min.js:4 
k.cors.a.crossDomain.send                              jquery.min.js:4 
n.extend.ajax                                          jquery.min.js:4 
n.(anonymous function)                                 test.html:40 
switchLED                                              test.html:11 
onclick

@dag, it caused some head scratching, but as it seems there were two issues.
One temporary authorization problem with my own test code and one with this part of your web code

    ...
    if(value==1){
      newValue=="HIGH"; // <-- no double equal signs!
    }
    else if(value==0){
      newValue=="LOW";  // <-- no double equal sign!
    }
    ...

To catch any other case you could do this in the Core firmware

int ledControl(String state)
{
  if(state.startsWith("HIGH"))
  {
    digitalWrite(led1, HIGH);  // Turn ON the LED pins
    return 1;
  }
  else if(state.startsWith("LOW"))
  {
    digitalWrite(led1, LOW);  // Turn OFF the LED pins
    return 0;
  }
  else
  {
    for (int i=0; i < 10; i++)
    {
      digitalWrite(led1, !digitalRead(led1));
      delay(50);
    }
  }
  return -1;    
}

3 Likes

@ScruffR thanks for the help, i didn’t see those two “==”