Spark Variable and Publish/Subscribe trouble [SOLVED]

Hi All,

I am trying to send temperature readings from one core to another. I think the correct way to do this is by using a spark variable.

The MAX 31855 board is giving me data through the spark dev serial monitor. The CLI is telling me that I have published a variable from the core in question. What’s the problem then? Well the serial data is a reasonable 24 deg C but the CLI variable data is a chilly 0 Deg C. Now I know it is winter but…

my code is as follows,

  /***************************************************
  This is an example for the Adafruit Thermocouple Sensor w/MAX31855K

  Designed specifically to work with the Adafruit Thermocouple Sensor
  ----> https://www.adafruit.com/products/269

  These displays use SPI to communicate, 3 pins are required to
  interface
  Adafruit invests time and resources providing this open source code,
  please support Adafruit and open-source hardware by purchasing
  products from Adafruit!

  Written by Limor Fried/Ladyada for Adafruit Industries.
  BSD license, all text above must be included in any redistribution
 ****************************************************/

#include "math.h"
#include "ADAFRUIT_MAX31855.h"

int thermoCLK = A3;
int thermoCS = A2;
int thermoDO = A4;

Adafruit_MAX31855 thermocouple(thermoCLK, thermoCS, thermoDO);
double c = 0;
void setup() {
  // open serial terminal and press ENTER to start
Spark.variable("temperature",&c, DOUBLE);
  Serial.begin(9600);
  while(!Serial.available()) SPARK_WLAN_Loop();

  Serial.println("MAX31855 test");
  // wait for MAX chip to stabilize
  delay(500);
}

void loop() {
  // basic readout test, just print the current temp
   Serial.print("Internal Temp = ");
   Serial.println(thermocouple.readInternal());

   double c = thermocouple.readCelsius();
   if (isnan(c)) {
     Serial.println("Something wrong with thermocouple!");
   } else {
     Serial.print("C = ");
     Serial.println(c);

   }
   //Serial.print("F = ");
   //Serial.println(thermocouple.readFarenheit());

   delay(1000);
}

I have not tried to pick this data up with the other core yet (I want to send it to my shiny new 16 x 32 LED matrix!)

I have been checking the process at each step by using the serial port monitor and the CLI. Looks like it is broken somewhere in the code?

When a spark variable is defined why does the second reference in brackets have an & in front of it?

BTW Merry Christmas one and all. I wished for a photon but all I got was an “I owe you” note from santa!!
:smile:

Hi @Julian

Merry Christmas to you too! Your problem is that you have both a global variable “c” and a local variable “c”. One you define the local variable using its type (double) with the same name, you can’t see the global one any more.

Change the line above to just assign c, not define it as a double:

 c = thermocouple.readCelsius();
1 Like

And a Happy New Year!!

I bring glad tidings… You sorted it. thank you very much. Serial port and spark variable now reading the same.

To get the data to the other core should I use the subscribe command? If I have subsrribed to a data feed does that variable then become exposed to the new core. By which I mean, if I want to display the variable on a matrix display can I, after subscribing to it, just print that variable to the matrix.

I suppose I am asking if you subscribe to a spark variable in some code does that variable then become populated with the data comming to it from the cloud?

Thanks again Brian,
Cheers,

@Julian, if you want to subscribe to data from another Core you can’t us a Spark.variable but you’d have to Spark.publish it as a string value.

This was also @peekay123 's suggestion here

1 Like

@ScruffR, Merry Christmas!,

So, Publish is to subscribe as GET is to variable?

I was thinking that if I take the data as a value I could write it straight to the matrix?

It just looked like spark variable would fit my case better, but maybe not?

http://docs.spark.io/firmware/#spark-variable
Expose a variable through the Spark Cloud so that it can be called with GET /v1/devices/{DEVICE_ID}/{VARIABLE}.

:smile:

@Julian, thanks a lot and a lovely time to you too!

It’s not quite the same. Variables are retrieved when a GET “asks” for it but another Core would have to create a http-GET request to do this, which is a bit cumbersome.
On the other hand publish does push the data into the cloud actively and any subscriber can observe this and act accordingly.

But since you do get a string anyway, you can forward it to your LED matrix just as well.

I think that eventually the Spark cloud will allow core-to-core variables but for right now, the only core-to-core transfer using just the cloud is publish and subscribe.

Sometimes using both is good! You can publish a value to another core and put it in a Spark variable for a web application.

1 Like

Thank you for your answer. That seems like a good ides, to have both the web and cloud option open.

Can I publish my data as a variable?

I wondered if I coud add this line in but it doesn’t like it,

Spark.publish(“Thermocouple temperature”, c);

When I compile this it say’s that there is no matching spark function for call to SparkClass::publish(const char [25], double&)

Is there a list of error statements somewhere?

What am I doing wrong? :smile:

@Julian, the minimal way you would do this is as follows

For the sender

double c = 0;

void setup()
{
  Spark.variable("ThermoCouple", &c, DOUBLE);
}

void loop()
{
  c = getItSomeHow();
  
  Spark.publish("ThermoCoupleEvent", String(c));  // <-- observe STRING

  delay(1000);
}

For the subscriber


void yourEventHandler(const char* Event, const char* Data)
{
  doSomethingWith(Data);
}

void setup()
{
  Spark.subscribe("ThermoCoupleEvent", yourEventHandler);
}

BTW: Your error message goes along with what I stated above

2 Likes

Thank you very much for your help. I haven’t done much with strings. I have a feeling that might change soon!

Thanks

1 Like

@ScruffR,

Just an update and a couple of further questions.

The first core is now publishing an event called, ThermoCoupleEvent. I can see the published data through the CLI by using the “spark subscribe ThermoCoupleEvent” command.

So it is the other half I am having trouble with. When I run that code it should send the variable “DATA” to the serial port, however I am not getting anything through.My questions are,

Why use an event handler subroutine? why not just have a “spark.subscribe” command?

In the event handler which of the variables are ones that should be changed to suit a particular case? In other words, my handler statement at the moment looks like this,

void myHandler(const char *event, const char *data)

should I be changing the *event to *ThermoCoupleEvent?
I notice from the CLI subscribing data stream that it refers to a variable called DATA so would I be correct to assume that any information you are subscribing to come out in the subscriber code as a string called DATA?

The subscribe statement in the code for the second core is,
Spark.subscribe("ThemoCoupleEvent", myHandler);

Cheers :smile:

You could liken your question about Spark.subscribe() to signing an actual magazine subscription.
Would you expect having to sign and file a new subscription form for each issue of the magazine you want to have sent each week?

I guess not - and the same with Spark.subscribe(). With the magazine subscription you only give an address and you expect the magazine to hit that respective post box over and over again, without further ado.
And this post box in the Spark world is your EventHandler routine. Once the event hits the handler, it will do its job.

But your job is to define what should happen inside the handler body - you don’t need to change the parameter names (as you suggested), you need to take the parameters as they are and do something with their contents.

Try this

void myHandler(const char *event, const char *data)
{
  Serial.println(event);
  Serial.println(data);
}

and have a look what happens.

Actually this is not that much different to what I wrote earlier

1 Like

Thanks for your answer, I have

void myHandler(const char *event, const char *data)
{

  Serial.println(event);
  Serial.println(data);
}

added the above code, set the thermocouple running, checked there is data there by CLI and by a serial port monitor. Then looked on the other port for the incoming (event) and (data). Nothing is turning up.

I have tried to put the subscribe statement in the loop(); and in the setup(), it didn’t seem to make any difference, neither worked. By the way where should the subscribe statement go?

My code (the relavent bit) is now,

RGBmatrixPanel matrix(A, B, C, CLK, LAT, OE, true);

void setup() {
  Serial.begin(9600);
  Time.zone(0);
  matrix.begin();

  matrix.setTextSize(1);    // size 1 == 8 pixels high

  // print each letter with a rainbow color
  matrix.setTextColor(matrix.Color333(4,4,4));
Spark.subscribe("ThemoCoupleEvent", myHandler);

}

:frowning:

But it is lots of fun :slight_smile: getting there.

Thank you for your help.

As said earlier Spark.subscribe() belongs into setup()

To test if your handler gets called at all, you could do this

void myHandler(const char *event, const char *data)
{
  digitalWrite(D7, !digitalRead(D7));  // blink the blue LED

  Serial.println(event);
  Serial.println(data);
}

void setup()
{
  Spark.subscribe("ThermoCoupleEvent", myHandler);

  pinMode(D7, OUTPUT);   // to make the blue LED "blinkable"
  Serial.begin(115200);  
}

In your code above you have a typo. You are missing a r in ThermoCoupleEvent:

Please double/triple check and carefully read your code and previous posts!

Thanks for that. I thought I had cut and pasted it!

It is working now.

By the way, should the subscribe statement go in the loop or in the setup or does it not matter?

I don’t know if you can re-allocate this thread to a more fitting title because it has moved on a bit from spark variable trouble!!

:smile:

1 Like

Please! Read the posts!

I’ve said it several times in different posts

and

putting into loop() would be like this

1 Like

@ScruffR, OK so I now have a smooth flow of data from the thermocouple through a publish command and subscribed to by another core. The receiving core is printing the data to a serial port.

:slight_smile:

When I reference the string “data” outside the handler, the code says that it is not declared in the scope. So I put the matrix.begin();, matrix.print(data); commands into the myHandler subroutine, which works a bit but the loop I have set up wipes the display, the effect of which is that the temperature flashes on and off the matrix.

Or is there some way I can expose the string “data” outside the myHandler() subroutine?

@Julian, depending on the other things you want to display there are roughly two ways to go.

If you have a lot of other data that doesn’t have anything to do with your thermo reading you’d probably go the “expose data” way, that you already suggested.
But if almost everything you want to display revolves around the temp reading, then you could consider taking all the display stuff out of loop into your event handler.

If you’d go the “expose” way you’d do something like this

char displayText[64];

void yourHandler(const char *event, cons char *data)
{
  strcpy(displayText, data);  // this copies the incoming string into your local buffer
}

Once you have the data in your local buffer, you can use it anywhere in your code.

If you want to go the other way, it would be good if you could show your loop() code to decide what goes and what not.

1 Like

Evey day is a school day, thanks for that never heard of strcpy ?

So…I have (you have) got it working, remote thermocouple displayed on a 16x32 matrix.

WOW :smile: Thanks for your help,

@ScruffR, @peekay123 & @bko.

2 Likes

:+1: That’s the best, when a plan works out :+1:

But usually when you reached your goal it’s not long before you get fidgety and want more, MORE, MORE - wuahhhhahaha :stuck_out_tongue_winking_eye: !!!

Ahm - sorry about that :blush: :wink:

How about different colors (cold blue -> warm red)

I’m curious what you’ll come up with next - we will be there to assist!

2 Likes