🎁📬❄️📦Adafruit Holiday Shipping Deadlines 2019: Please place all UPS 2 Day orders by 11am Monday, December 16 📦❄️📬🎁
0

Using a pushbutton to toggle a dashboard switch
Moderators: adafruit_support_bill, adafruit

Forum rules
If you're posting code, please make sure your code does not include your Adafruit IO Active Key or WiFi network credentials.
Please be positive and constructive with your questions and comments.

Using a pushbutton to toggle a dashboard switch

by jefish on Sun Dec 01, 2019 4:06 am

I'm building a IO-controlled xmas tree light switch, and have run into a problem. My criteria are:

1) Toggle switch on dashboard (powerswitch feed) to tell ESP to turn a relay on or off <done>
2) Light on the dashboard (powerlight feed); value set from the ESP after the relay is switched, to show message success <done>
3) Physical momentary button to manually toggle the IO powerswitch <record scratch>

The issue I'm trying to solve with #3 is this; I turn off the lights with the IO toggle. Wife gets up in the morning and wants to turn them back on, which would be a lot easier with a physical button. So far I've gotten halfway there. :)

I'm using powerlight as a value, and want to set the powerswitch to the opposite of powerlight (toggle it on or off based on the current state). I've tried using powerswitch as a the source state, but was getting some double-replies from IO. Also tried reading the RELAY_PIN value and using that as the source. Any value would be fine, whatever I can use to say "set powerswitch to not-that."

So, if the dashboard powerlight is On, pressing the button WILL turn off powerswitch.
Serial shows:
23:26:24.600 -> Button pressed
23:26:24.847 -> IO switch is OFF

If the dashboard powerlight is Off, pressing the button will NOT turn on powerswitch.
Serial shows:
23:26:00.903 -> Button pressed
23:26:01.081 -> IO switch is OFF

Code: Select all | TOGGLE FULL SIZE
#include "config.h"
#include <ESP8266WiFi.h>
#include <WiFiUdp.h>
#include <ArduinoOTA.h>
#define LED_PIN 2
#define RELAY_PIN 4
#define BUTTON_PIN 14

const char* ssid = "SSID";
const char* password = "PASS";
AdafruitIO_Feed *powerswitch = io.feed("powerswitch");
AdafruitIO_Feed *powerlight = io.feed("powerlight");

int button;

void setup() {
  pinMode(LED_PIN, OUTPUT);
  pinMode(RELAY_PIN, OUTPUT);
  pinMode(BUTTON_PIN, INPUT);
  digitalWrite(LED_PIN, HIGH);
  digitalWrite(RELAY_PIN, LOW);

  Serial.begin(115200);

  WiFi.begin(ssid, password);
  while (WiFi.waitForConnectResult() != WL_CONNECTED) {
    delay(3000);
    ESP.restart();
  } 
 
  ArduinoOTA.setHostname("TreeESP");
  ArduinoOTA.begin();

  Serial.print("Connecting to Adafruit IO");
  io.connect();

  powerswitch->onMessage(handleMessage);

  while(io.status() < AIO_CONNECTED) {
    Serial.print(".");
    delay(1000);
  }
  Serial.println();
  Serial.println(io.statusText());
  powerswitch->get();
}

void loop() {
  io.run();
  ArduinoOTA.handle();

  button = digitalRead(BUTTON_PIN);

  if (button == LOW) {
    Serial.println("Button pressed");
    powerlight->get();
    powerswitch->save(!powerlight);
  }

}

void handleMessage(AdafruitIO_Data *data) {
 
  if(data->toPinLevel() == HIGH) {
    Serial.println("IO switch is ON");
    digitalWrite(RELAY_PIN, HIGH);
  }
  else {
    Serial.println("IO switch is OFF");
    digitalWrite(RELAY_PIN, LOW);
  }
  digitalWrite(LED_PIN, !data->toPinLevel());
  powerlight->save(data->toPinLevel());
}

jefish
 
Posts: 44
Joined: Fri Sep 12, 2014 2:08 am

Re: Using a pushbutton to toggle a dashboard switch

by jefish on Mon Dec 02, 2019 5:00 pm

Short version: I'd like to single-press a physical button to toggle a aio switch on/off or 1/0.

jefish
 
Posts: 44
Joined: Fri Sep 12, 2014 2:08 am

Re: Using a pushbutton to toggle a dashboard switch

by llaverne on Fri Dec 06, 2019 12:13 pm

If you know how to use 2-way communication, then simply use a register/variable in the Arduino sketch to keep track of switch state. Then, at each connection to IO, register to the switch topic, check it's on-line state, and do a comparison to the Arduinos recorded switch state. If the Arduino says it's OFF, but IO says ON, then you know that the online switch was activated, so flip the relay to ON. If on he other hand, when the Arduino connects to IO, the switch is OFF in IO, but the Arduino says ON (that is, someone pressed the physical switch), then simply send ON to IO. Repeat.

llaverne
 
Posts: 1
Joined: Fri Oct 04, 2019 1:36 am

Re: Using a pushbutton to toggle a dashboard switch

by jefish on Sat Dec 07, 2019 3:28 am

Yep, that's what I've been trying. The trouble is, the state of powerlight always comes back as 1, even when the dashboard shows it at 0. I did find that I wasn't fetching the powerlight state when pressing the button, that has been remedied in the new code below. But still having troubles.

- In setup, it does an initial powerswitch->get() and sets the relay and onboard LED to echo that state. This works fine.
- In handleMessage, it monitors messages from io powerswitch and sets the relay, onboard LED, and io powerlight value to echo any changes to that state. This also works.
- But in loop, it runs powerlight->get() on buttonpress and sets that to int lightstate. This is where things fall apart.

If the dashboard switch and light are on and I toggle the switch, I get
IO powerswitch is now OFF
Setting IO powerlight to 0

If the dashboard switch and light are off and I toggle the switch, I get
IO powerswitch is now ON
Setting IO powerlight to 1

This is all fine.

If the dashboard switch and light are on and I press the physical button, I get
Button pressed
IO powerlight is currently 1 // this looks right, but stand by
Setting IO powerswitch to 0 // this shows that my "set switch to not-light" is working
IO powerswitch is now OFF // this is handleMessage reacting to the loop and...
Setting IO powerlight to 0 // setting the light to match the new switch state

This is also fine; the local LED and relay shut off, and the dashboard state is accurate.

But the problem is revealed when the dashboard switch and light are off and I press the physical button
Button pressed
IO powerlight is currently 1 // **THIS IS WRONG**
Setting IO powerswitch to 0 // it already was
IO powerswitch is now OFF // as I said
Setting IO powerlight to 0 // and so was this

I've tried using if lightstate == 1 { else, and if lightstate == HIGH { else, and ... jeez, a few other things. Unless powerlight->get() comes back with a real value, I'm sunk.

Latest code here
Code: Select all | TOGGLE FULL SIZE
#include "config.h"
#include <ESP8266WiFi.h>
#include <WiFiUdp.h>
#include <ArduinoOTA.h>
#define LED_PIN 2
#define RELAY_PIN 4
#define BUTTON_PIN 14

const char* ssid = "SSID";
const char* password = "PASS";
AdafruitIO_Feed *powerswitch = io.feed("powerswitch");
AdafruitIO_Feed *powerlight = io.feed("powerlight");

int button;
int lightstate;

void setup() {
  pinMode(LED_PIN, OUTPUT);
  pinMode(RELAY_PIN, OUTPUT);
  pinMode(BUTTON_PIN, INPUT);
  digitalWrite(LED_PIN, HIGH);
  digitalWrite(RELAY_PIN, LOW);

  Serial.begin(115200);

  WiFi.begin(ssid, password);
  while (WiFi.waitForConnectResult() != WL_CONNECTED) {
    delay(3000);
    ESP.restart();
  } 
 
  ArduinoOTA.setHostname("TreeESP");
  ArduinoOTA.begin();

  Serial.print("Connecting to Adafruit IO");
  io.connect();

  powerswitch->onMessage(handleMessage);

  while(io.status() < AIO_CONNECTED) {
    Serial.print(".");
    delay(1000);
  }
  Serial.println();
  Serial.println(io.statusText());
  powerswitch->get();
}

void loop() {
  io.run();
  ArduinoOTA.handle();

  button = digitalRead(BUTTON_PIN);

  if (button == LOW) {
    Serial.println("Button pressed");
    lightstate = powerlight->get();
    Serial.print("IO powerlight is currently ");
    Serial.println(lightstate);
    Serial.print("Setting IO powerswitch to ");
    Serial.println(!lightstate);
    powerswitch->save(!lightstate);
  }
}

void handleMessage(AdafruitIO_Data *data) {
 
  if(data->toPinLevel() == HIGH) {
    Serial.println("IO powerswitch is now ON");
    digitalWrite(RELAY_PIN, HIGH);
  }
  else {
    Serial.println("IO powerswitch is now OFF");
    digitalWrite(RELAY_PIN, LOW);
  }
  digitalWrite(LED_PIN, !data->toPinLevel());
  Serial.print("Setting IO powerlight to ");
  Serial.println(data->toPinLevel());
  powerlight->save(data->toPinLevel());
}

jefish
 
Posts: 44
Joined: Fri Sep 12, 2014 2:08 am

Please be positive and constructive with your questions and comments.