I’ve got four Particle Cores. I want to have each of them hooked up to various buttons and switches and various LEDs. I want to have them selectively react to button presses on other Cores.
/*
Core1.
*/
int sendLedPin = D7; //choose the pin for the send (local) LED
int inputPin = D4; //choose the input pin (for a pushbutton)
int receiveLedPin = D0; //choose the pin for the receive (Core2-dependent LED)
int val = 0; //variable for reading the pushbutton pin status
int sendLedVal = 0; //variable for keeping the state of the local pushbutton dependent LED (D2)
void ledTwoToggle(const char *toggle, const char *onOff); //handler function for Spark.subscribe()
void setup() {
pinMode(receiveLedPin, OUTPUT); //Set the pin controlling the Core2-dependent LED as an OUTPUT
pinMode(sendLedPin, OUTPUT); //Set the pin controlling the local pushbutton-dependent LED as an OUTPUT
pinMode(inputPin, INPUT); //Set the pin connected to the pushbutton as an INPUT
digitalWrite(sendLedPin, LOW); //Ensure the local LED is set to off to begin with
digitalWrite(receiveLedPin, HIGH); //Ensure the local LED is set to off to begin with
Spark.publish("Core1Toggle", "State", 0); //Set up Spark.publish() so that the state of the local LED is published to the Spark Cloud PRIVATELY
Spark.subscribe("Core2Toggle", ledTwoToggle); //Set up Spark.subscribe() so that the state of Core1's Led is recorded and handled by ledTwoToggle
}
void loop() {
val = digitalRead(inputPin); //read value of pushbutton
if (val == LOW) { //if clause activated if pushbutton pressed and thus inputPin reads LOW
sendLedVal = !sendLedVal; //if clause activated if pushbutton pressed and thus inputPin reads LOW
digitalWrite(sendLedPin, sendLedVal ? HIGH : LOW); //write the appropriate HIGH/LOW to the sendLed pin to turn it ON/OFF
Spark.publish("Core1Toggle", sendLedVal ? "ON" : "OFF"); //publish the state to the Spark Cloud as ON/OFF
delay(250); //primitive button debouncing
}
}
void ledTwoToggle(const char *toggle, const char *onOff){ //handler function for Spark.subscribe()
if (strcmp(onOff, "ON") == 0){ //if sendLed on Core2 is ON according to Spark.publish()
digitalWrite(receiveLedPin, HIGH); //then turn on receiveLed
} else if (strcmp(onOff, "OFF") == 0){ //if sendLed on Core2 is OFF according to Spark.publish()
digitalWrite(receiveLedPin, LOW); //then turn off receiveLed
}
}
which just seems rather complicated for the act of transmitting a button press over the interwebs to another Core and turning an LED on. Anyway if that’s how it has to be, that’s how it has to be. I wondered if someone would mind just commenting on whether there is an easier way to do this before I set about adapting/writing more code. Thank you!
Thank you - I will try that tomorrow morning - much appreciated.
I have another version of the code with some non-blocking debounce but it’s using a library, which I had to incorporate into the body of the code (am I right I can’t ‘call’ on libraries in separate files like I can with Arduino?).
This is much neater, though, so thank you!
So for every separate state I want to keep track of I’ll need a separate “void ledtwotoggle” ? Fine if so, I’ll get copying and pasting!
No, if you wrap your sending device ID and any other useful info into your event name and data payload you can just get along with one handler.
There might me some doc reading to be done, but one hint is that the event name you are subscribing to is only a prefix filter (e.g. CoreToggle would fire for CoreToggle1andCoreToggle2and evenCoreToggleAnyOtherSuffix).
Just check the contents of toggle along side onOff.
If you use your DeviceID rather than an arbitrary number you can even flash the same code to all of your Cores and each Core would know if it's receiving own events or one of the others without the need to set that number in code for each individual Core.
This sounds great. I’m trying to wrap my head around it. I keep revisiting your message and having another read of it and it does get clearer each time.
I’ll try and find some documentation to read. Thanks.
Thanks @BulldogLowell, once I changed particle.subscribe etc back to spark.subscribe it compiled and uploaded without a hitch and you’re quite right, without all the comments, it’s actually easier to read! So thanks.
Bit of a weird problem… I seem to have a problem with a floating button. Moving (like raising my arm) anywhere near the prototyping area causes the button to act as if it’s been pressed really quickly.
But this shouldn’t be happening, right? Because I’m using the internal pullup on the input button to avoid this?
pinMode(inputPin, INPUT_PULLUP);
Bit confused. It’s as if something’s acting as an antenna and transmitting my movements to the Core.
oK, I’ll give it a go. Although I have just gone back to basics and tried the arduino “button” example sketch (but with internal pullup on rather than using an external one) and it’s stable as anything. It’s almost like it’s the complication of spark publish/subscribe which is introducing the noise. Which doesn’t make any sense, right?
Hi @ScruffR, believe it or not now has been my first opportunity to have a play with your suggestion and try to implement it.
The good news? I have no floating problems at all anymore. Everything is as solid as a rock. I presume this is down to the new firmware. I am delighted.
The slightly less good news is that I cannot figure out how I can get away with only using one ‘voidledtwotoggle’, because I have noticed in my attempt to implement to “share the void” that the void controls the status of digitalwrite to my output LED.
Any help in making one void work for multiple buttons and multiple LEDs would be much appreciated because I am aware I cannot have more than four spark subscribe/spark publish. Thanks again
While there is a limit for subscriptions, there is none for publishes and when you subscribe to e.g. "myPrefix" your handler will be triggered for anything that starts with "myPrefix", so you can use do e.g. Particle.publish("myPrefixLED1", "ON") and Particle.publish("myPrefixLED2", "OFF") and both wil trigger the same handler. To check which LED is meant, you look at the first parameter you called *toggle.
Or you send something like "LED1=OFF"/LED2=ON", split this up and use the seperated values.