Tutorial: Spark Variable and Function on One Web Page

Hi @Dup

If you are doing an analogRead of a pin that is not driven by anything, you will just get random values. Tinker is just am example–you can do your own thing very easily.

If you want to use a Spark.function to set a parameter, that is, something you want to change to “tune” you code to behave better on the fly, that is a perfect use. You would just do:

int myParam = 0;  // or other initial value

void setup()
{
  Spark.function("setparam", setParam);
  Spark.variable("getparam", &myParam, INT);
  // whatever other setup you need
}

void loop() {
//you code that uses myParam
}

int setParam(String paramValue) {
    myParam = paramValue.toInt();
    return 0;
}

Now from the web page you can read and set the parameter value and in your program, you just use myParam however you want.

1 Like

Thanks!
I added int setParam(String paramValue); above setup

and I get {
“id”: “xxxxxxxxxxxxxxxxxxxxxx”,
“name”: “xxxdevice_namexxxxx”,
“last_app”: null,
“connected”: true,
“return_value”: -1
}

when using this
curl https://api.spark.io/v1/devices/xxxxxxxxxxxxxxx/setParam -d access_token=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -d “myParam=188”

Hi @Dup

I just tested the exact code I posted above it worked great for me. OK I think I see what is wrong–you are calling setParam in curl and you should be calling setparam, all lower case! On the web, the name is the thing in double quotes when you setup the Spark.function.

curl  https://api.spark.io/v1/devices/<<dev id>>/setparam?access_token=<<access token>> -d "myparam=17"
{
  "id": "<<dev id>>",
  "name": "<<name>>",
  "last_app": null,
  "connected": true,
  "return_value": 0
}

curl  https://api.spark.io/v1/devices/<<dev id>>/getparam?access_token=<<access token>>
{
  "cmd": "VarReturn",
  "name": "getparam",
  "result": 17,
  "coreInfo": {
    "last_app": "",
    "last_heard": "2014-05-17T14:47:57.347Z",
    "connected": true,
    "deviceID": "<<dev id>>"
  }
}

bko!
awesome!! it worked !!

thanks again!

1 Like

I dont yet have a servo, so can you explain how I can read a analogue input and or a temperature ic

Hi again @kiwibird1

First try looking at this basic example for how to use a Spark variable and a temperature sensor

http://docs.spark.io/#/examples/measuring-the-temperature

Sorry–this tutorial here may be a bit advanced. I should have pointed you to this tutorial which handles the exact thing you want to do:

Sorry I cut-and-pasted the wrong tutorial pointer for you!

Hi bko. I get the temp sensor bit, but not sure how to get that via the html file. Thanks for your patience as my knowledge of some of these specs its very low.

this code gives red led flashing since the servo section is added.
Needs factory reset to fix
Can anyone help?

#include "spark_disable_wlan.h"
#include "spark_disable_cloud.h"

// Read temperature
// -----------------

// Create a variable that will store the temperature value
int temperatureraw = 0;
double voltage=0;
double temperature=0;

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

// name the pins
int led1 = D0;
int led2 = D1;
int led8 = D7;
int wififailurecounter = 0;
int BeepCounter = 0;

int ledControl(String command);

// controlling servo
Servo myservo;  // create servo object to control a servo

int pos = 0;    // variable to store the servo position


void setup()
{
    Spark.variable("temperature", &temperature, DOUBLE);

    Serial.begin(9600);
    Serial.println("Booting up");
    //register the Spark function
    Spark.function("brew", brewCoffee);

    // Connect the temperature sensor to A7 and configure it
    // to be an input
    pinMode(A7, INPUT);

    //Register our Spark function here
    Spark.function("led", ledControl);

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

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

    myservo.attach(A0);  // attaches the servo on the A0 pin to the servo object
    Spark.function("setpos", setPosition);
    Spark.variable("getpos", &pos, INT);
}

void loop()
{
    // Keep reading the temperature so when we make an API
    // call to read its value, we have the latest one
    temperatureraw = analogRead(A7);
    voltage = ( (double)temperatureraw * 3.3)/4095;

    temperature  =(voltage-0.5)*100;


    //digitalWrite(led1,LOW);
    
    
    // delay(1000);

    // Prints out the network parameters over Serial
    Serial.println(Network.SSID());
    Serial.println("test");
    Serial.println("test:");
    Serial.println("wififailurecounter:");
    Serial.println(wififailurecounter);
    Serial.println(Network.gatewayIP());
    Serial.println(Network.subnetMask());
    Serial.println(Network.localIP());
    Serial.println(Network.RSSI()); // strength -127 = no signal.
    Serial.println("wififailurecounter:");
    Serial.println(wififailurecounter);

    
    delay(2000);
    
    digitalWrite(led8,HIGH);
    digitalWrite(led1,HIGH);
    delay(5);
    
    BeepCounter=wififailurecounter;
    while (BeepCounter >0) //IF IT FAILES, BEEP ONCE FOR EACH FAILURE
    
    {
        BeepCounter--;
        digitalWrite(led1,HIGH);
        delay(500);
        digitalWrite(led1,LOW);
        delay(500);
        
    }
    
    
    digitalWrite(led8,LOW);
    digitalWrite(led1,LOW);
    
    //delay(1000);
    brewCoffee("coffee");
}

// 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




//this function automagically gets called upon a matching POST request
int brewCoffee(String command)
{
    //look for the matching argument "coffee" <-- max of 64 characters long
    if(command == "coffee")
    {
        //  digitalWrite(led8,HIGH);
        //do something here
        //activateWaterHeater();
        //activateWaterPump();
        return 1;
    }
    else return -1;
}


int ledControl(String command)
{
    int state = 0;
    //find out the pin number and convert the ascii to integer
    int pinNumber = (command.charAt(1) - '0') - 1;
    //if (command=="8") pinNumber=7;
    //if (command=="2") pinNumber=1;
    //if (command=="1") pinNumber=0;
    //Sanity check to see if the pin numbers are within limits
    if (pinNumber < 0 || pinNumber > 7) 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);
    // digitalWrite(7, state);

    return 1;
}

int setPosition(String posValue) {
    pos = posValue.toInt();
    myservo.write(pos);
    return 0;
}

So at the beginning of your code, you turn off both the wireless LAN and the Spark cloud. Do you ever turn them back on?

I am not sure I see what you are trying to do–without both the cloud and the WLAN, the Spark variables and functions will not work.

when the first two lines are removed, it works. :slight_smile: The servo home is set wrong to it jams at under 5 degrees.
How thing works erratically intermittently. Will replace servo when I get a chance. lateny is about 2 seconds. A bit slower than I would like, but I can live with that.

Glad it is working! You can set the pos variable to 90 to center the servo at power up, if you like.

Thank you for an excellent tutorial! Unforunately I am having difficulty, but it’s with the javascript.

Why does this concatenation not work? Say I have 255 entered into a text input field with id=‘rVal1’, if I try to put this value in a string like this:

var pr = "pr=";
var prval = document.getElementById('rVal1').value.toString(256);
var pg = ",pg="
var term = pr + prval + pg;
document.getElementById('rVal1').innerHTML = term; renders as
pr=,pg=

But, document.getElementById(‘rVal1’).innerHTML = prval; renders as


255

Hi @Elijah

The toString() method works on a numeric object like an integer or floating point number. If given an argument like you do with 256 above, it treats that as the base, 2 for binary, 10 for decimal, 16 for hex. But 256 is not a legal base.

var pr = "pr=";
var prval = document.getElementById('rVal1').value.toString();
var pg = ",pg="
var term = pr + prval + pg;

Then term should be the string “pr=255,pg=”

What string are your trying to get?

[Issue solved: The problem was defining variables outside of the function scope where document.getElementById(‘rVal1’).innerHTML = term;was declared (see HTML below), so by moving the var pr, var prval, var pg,andvar term lines to within setColor() { } it works (without 256 argument to toString, thank you @bko)!

I think I was a little too liberal with my interpretation of ‘radix’, but this does not appear to be root cause: Here is basic HTML to reproduce the issue (js/jquery.js) refers to latest stable .min from jquery.org and downloaded to a local directory /js/ and renamed jquery.js:


The following code contains an error in the javascript, see top of post for fix

<code=“lang-auto”><html>
<script src=“js/jquery.js” type=“text/javascript” charset=“utf-8”></script>
<body>
<div class=“container”><div class=“control”><div><label>R</label><input type=“text” id=“rVal1” /></div></div></div>
<button type=“button” id=“colorsel” onclick=“setColors()”>Change colors!</button>
<p>Debugging Info: </p>
<i id=“returnVal”>Output…</i>
<button type=“button” onclick=“changeText()”>Grab rVal1</button>
<script type=“text/javascript”>
function changeText() {
var userInput = document.getElementById(‘rVal1’).value.toString();
document.getElementById(‘returnVal’).innerHTML = userInput;
}
</script>
<script type=“text/javascript”>
var pr = “pr=”;
var prval = document.getElementById(‘rVal1’).value.toString();
var pg = “,pg=”;
var term = pr + prval + pg;
function setColors() {
document.getElementById(‘returnVal’).innerHTML = term; //renders pr=,pg=
}
</script>
</body>
</html>
1 Like

Nice example Brian <@bko>,

Great job, this should open up a world of possibilities for everyone!

My idea light bulb is burning brightly :smile:

Performance Issue:
I noticed that adding a couple of JSON variable requests to the “window.setInterval” 1 second tasks, the updates do not occur at 1 second intervals. In fact, this results in my Spark seemly to lose connection with the cloud intermittently (The blue LED flickers for a while and then returns to the normal pulsing).

This might be an issue with jQuery/javascript.But it is definitely annoying.

I was wondering if there is a method available from the Spark Code side to pack multiple variables in a single JSON structure returned from the POST?

Let’s say a variable “loopcount” returned:
{
“cmd”: “VarReturn”,
“name”: “loopcount”,
“result”: 1209,
“coreInfo”: {
“last_app”: “”,
“last_heard”: “2014-06-27T15:55:03.840Z”,
“connected”: true,
“deviceID”: “”
}
}

Can we have multiple variable returned?

For example:
{
“cmd”: “VarReturn”,
“name”: “loopcounts”: {
“loop1_result”: ,
“loop2_result”: ,
“loop3_result”: ,
}
“coreInfo”: {
“last_app”: “”,
“last_heard”: “2014-06-27T15:55:03.840Z”,
“connected”: true,
“deviceID”: “”
}
}

It would seem to be an insignificant time difference whether 1 or 10 variables are returned from a single Query,
which would be much more efficient.

Is this possible?

HI @surfnturf57

You should see how I do this in my publishing a JSON tutorial. You can return a C-style char array string as a Spark variable and then parse the string as a JSON.

@bko I’m a newbie. So the total power should be +5V? I tried but its not powering up. What kind of power supply are you using, Can you please suggest?

Hi @shoaibuddin

I am away right now but briefly the servo needs +5v to operate but the Spark core can handle 3.3v or 5v depending on how you hook it up.

If look at the picture in the tutorial I am using a 5v supply for the servo and connecting it to the Vin pin which is the input side of the 3.3v regulator so the core gets 3.3 just like when you are using USB for power.

Hi bko!

Hi,
My code seems to run fine. I can post a function and I can get a variable. However after a while, it appears that the core stops talking to the cloud. I have collected data for hours but this AM as soon as I jumped on my webpage, I get an “error timeout”. I believe it is tied to the functions via the variables. I am wondering if this is similar to the issue with “Variables with strings longer than 9 chars”?

here is what I have in my code (4 different settings)

int setReset(String resetValue);
int myReset = 0;

void(setup)
Spark.function(“setreset”, setReset);
Spark.variable(“getreset”, &myReset, INT);

void loop()
int setReset(String resetValue) {
myReset= resetValue.toInt();
return 0;

anything will help!
thanks

Hi @Dup

Sorry I was away for a while.

How fast are you running the update on the web side? The second argument to window.setInterval which is 1000 in the example above is the time in milliseconds between calls to the function to updated the web page side of the variables. It is possible to do this too quickly and overload the Spark cloud host, so 1 sec (1000 ms) is a good minimum.

Which browser are you using? I like Chrome–it seems to run well for me both on PC and Mac.

1 Like