sinricpro / esp8266-esp32-sdk

Library for https://sinric.pro - simple way to connect your device to Alexa, Google Home, SmartThings and cloud
https://sinric.pro
Other
230 stars 124 forks source link

A push button? Relay? #44

Closed vanginger closed 4 years ago

vanginger commented 4 years ago

Hi

I have had a door opener for my garage door for years using Fauxmo. As you have rightly said, this way is flawed and in recent weeks trying to fix it, I have discovered Sinric and think it is a great solution. I have an ESP32 connected to a relay that operates a remote (to the garage) push switch. I only need it to press it, not to check the state or open/close. Just turn on very briefly to tell the lifter unit to open the door. I have used the Switch sketch and it does the job but, I presume as expected, it turns on and stays on or turns off and stays off. So I can get it to operate like this but it's not quite the right way and will constantly (electronically) hold the push button down rather than just pressing and letting go. I have tried putting in a delay and then telling it to turn off, but it is having no effect. Is there a sketch that is better suited to this idea? Or should I persevere with adapting Switch? I am usually okay at adapting other's code but not writing my own from scratch.

I am obviously missing something but I added the delay and what I thought might turn it off here: I presumed digitalwrite turns on/off the LED and the pin? I also tried switching HIGH and LOW around to no avail.

void handleButtonPress() { unsigned long actualMillis = millis(); // get actual millis() and keep it in variable actualMillis if (digitalRead(BUTTON_PIN) == LOW && actualMillis - lastBtnPress > 1000) { // is button pressed (inverted logic! button pressed = LOW) and debounced? if (myPowerState) { // flip myPowerState: if it was true, set it to false, vice versa myPowerState = false; } else { myPowerState = true; } digitalWrite(LED_PIN, myPowerState?LOW:HIGH); // if myPowerState indicates device turned on: turn on led (builtin led uses inverted logic: LOW = LED ON / HIGH = LED OFF) delayMicroseconds(5000); digitalWrite(LED_PIN, myPowerState?HIGH:LOW); // get Switch device back SinricProSwitch& mySwitch = SinricPro[SWITCH_ID]; // send powerstate event mySwitch.sendPowerStateEvent(myPowerState); // send the new powerState to SinricPro server Serial.printf("Device %s turned %s (manually via flashbutton)\r\n", mySwitch.getDeviceId(), myPowerState?"on":"off");

lastBtnPress = actualMillis;  // update last button press variable

} }

sivar2311 commented 4 years ago

Hi vanginger.

Sorry, i don't get exactly what you want to achive. Do you want to control your garagedoor using SinricPro (Alexa) ? Or do you want to control it via a push button, connected to your ESP? I am just asking, because the code you posted is only for the "manual controlling" part.

The switch example is made for Alexa (onPowerState function), and additionally for manual control (handleButtonPress function) including to return current state to SinricPro if the manual button was pressed.

I think a Switch is not the correct device for your project, because a switch is ON or OFF. SinricPro supports a garagedoor device (unfurtunately, garagedoor is supported only in the US by amazon) and a lock device.

Depending on which device type you want to use:

Both functions take a state parameter (boolean). false: open / unlock the door true: close / lock the door

If this state have changed to what it was before (true to false, or false to true), put the corresponding pin HIGH for a certain amount of time(*1) and then back to LOW.

*1: Don't use delays that lasts longer than 8 seconds...this is the maximum for Amazon alexa!

Please check garagedoor project i did with Doug using a Lock device and 2 reedswitches as endstops to detect and report garagedoor position. If you want to see this project in action, see Doug's youtube video

vanginger commented 4 years ago

Hi Silvar2311

Thanks for the reply. I have just watched the video and looked at the code, really interesting! Does your code need to be used in the US to work then with Alexa or is that not the same as the garagedoor supported by Alexa, and you developed your own? If that can be used anywhere, then I think I would like to look at that in summer (when I have a lot more time!) using the reedswitches as end sensors. (I am in the UK)

For now however, the garagedoor i was talking about is almost irrelevant. I just need something that presses a push button briefly when I say something along the lines of 'Alexa, turn the garage on'. Literally just that, it doesn't need to check anything. 2020-03-03 06 24 40 So, as the picture should hopefully show, ESP32 is connected to a relay that briefly turns on to press the remote wall switch when it is told to by Alexa. The code I used for it when I did it with Fauxmo is below. As it is, I don't need to detect if it is open or closed. It should work just as if we pressed the remote ourselves, just turning ON, irrelevant of whether it is open or closed. I am sure I could take something from your code or the code I used with Fauxmo, but at the moment I am not sure my programming skills are fully up to picking it out exactly. For example, I can't find an explanation of how the following works using the ?, : and 2 states for digitalwrite online, digitalWrite(LED_PIN, myPowerState?LOW:HIGH); // if myPowerState indicates device turned on: turn on led (builtin led uses inverted logic: LOW = LED ON / HIGH = LED OFF) Although as i don't need it to check the state at tho moment, I probably don't need all that?

Fauxmo code:

/**

define WIFI_SSID "****"//change your Wifi name

define WIFI_PASS "****"//Change your Wifi Password

define SERIAL_BAUDRATE 115200

fauxmoESP fauxmo; //declare switching pins //Change pins according to your NodeMCU pinouts

define Garage D1

// ----------------------------------------------------------------------------- // Wifi Setup // -----------------------------------------------------------------------------

void wifiSetup() {

// Set WIFI module to STA mode
WiFi.mode(WIFI_STA);

// Connect
Serial.printf("[WIFI] Connecting to %s ", WIFI_SSID);
WiFi.begin(WIFI_SSID, WIFI_PASS);

// Wait
while (WiFi.status() != WL_CONNECTED) {
    Serial.print(".");
    delay(100);
}
Serial.println();

// Connected!
Serial.printf("[WIFI] STATION Mode, SSID: %s, IP address: %s\n", WiFi.SSID().c_str(), WiFi.localIP().toString().c_str());

} // ----------------------------------------------------------------------------- // Device Callback // ----------------------------------------------------------------------------- void callback(uint8_t device_id, const char * device_name, bool state) { Serial.print("Device "); Serial.print(device_name); Serial.print(" state: "); if (state) { Serial.println("ON"); } else { Serial.println("OFF"); } //Switching action on detection of device name if ( (strcmp(device_name, "Garage") == 0) ) { // adjust the relay immediately! // if (state) { unsigned long start_time; unsigned long current_time; unsigned long elapsed_time;

    start_time = millis();

    do {
 digitalWrite(Garage, HIGH);
 current_time = millis();
 elapsed_time = current_time - start_time;

} while(elapsed_time < 1000); // (5min) (60s/min) (1000ms/s) digitalWrite(Garage, LOW); }

}

void setup() { //Initialize pins to Low on device start pinMode(Garage, OUTPUT); digitalWrite(Garage, LOW);

// Init serial port and clean garbage
Serial.begin(SERIAL_BAUDRATE);
Serial.println("FauxMo demo sketch");
Serial.println("After connection, ask Alexa/Echo to 'turn <devicename> on' or 'off'");

// Wifi
wifiSetup();

// Device Names for Simulated Wemo switches
fauxmo.addDevice("Garage");
fauxmo.onMessage(callback);

}

void loop() { fauxmo.handle(); }

sivar2311 commented 4 years ago

Does your code need to be used in the US to work then with Alexa or is that not the same as the garagedoor supported by Alexa, and you developed your own?

This was before amazon introduced garagedoordevice. It's based on lock device and will work in any country where amazon supports lock device. As you might have seen in my example code it is using SinricProLock.

For now however, the garagedoor i was talking about is almost irrelevant. I just need something that presses a push button briefly when I say something along the lines of 'Alexa, turn the garage on'. Literally just that, it doesn't need to check anything.

This is done in turnOnRelayAndWait function. The only thing you need to remove is checking the endstops.

So, as the picture should hopefully show, ESP32 is connected to a relay that briefly turns on to press the remote wall switch when it is told to by Alexa.

This is nearly the exact same configuration as we had in our garagedoor project.

For example, I can't find an explanation of how the following works using the ?, : and 2 states for digitalwrite online, digitalWrite(LED_PIN, myPowerState?LOW:HIGH)

This is the Conditional Operator You can use it to write something like this:

if (inverted == true) {       // if inverted is true...
  digitalWrite(PIN, LOW);  //   set pin to LOW
} else {                              // if inverted is false...
  digtalWrite(PIN, HIGH); //   set pin to HIGH
}

to this:

digitalWrite(PIN, inverted?LOW:HIGH); // if inverted is true set the pin LOW else set the pin HIGH
vanginger commented 4 years ago

Thanks for that, it's starting to make a lot more sense now.

Only had time for a quick look this morning, but tried sending your code to my DOIT ESP32 board before making any changes to it and it is saying D5 D6 and D7 are not declared. I thought that was just saying those pins are not on my board. I changed D6 and D7 to ones that are. D5 is on my board anyway.. but still same error.. weird! Will look properly later though.

sivar2311 commented 4 years ago

Unforunately ESP32 modules doesn't have those "D" pin definitions. You have to use GPIO numbers or make your own definitions:

#define D5     5
#define D6     6
#define D7     7
vanginger commented 4 years ago

Sorry, busy couple of days, I will have a proper look at the weekend. THanks again though. I changed the pins and it compiles fine now. Just as a very brief try, I changed the doorstate so that it would return always closed, as there is nothing to connect to pins 6 and 7, I made both endstop_closed to read false as door_closed. That is returning a error message though and not switching anything on: "message": "Device returned an error while processing the request!",

I will look properly at the weekend though.

sivar2311 commented 4 years ago

"Device returned an error while processing the request!" This will happen if the callback function is not implemented or return false.

The callback function itself always have to return true to indicate that the request was handled successfully.

To return the current door state, you have to set the state-variable (given as parameter):

bool onLockState(String deviceId, bool &lockState)
  ^                                          ^
  |                                          |
  |              is used to get and  --------+
  |              return the lock-state
  |
is used to return if the request was 
handled successfully (true) or not (false)

bool &lockstate <- the ampersand means, this is a reference to a variable and can be changed by the callback function. See c++ references

vanginger commented 4 years ago

It works!! Thank you so much for all your help. All I have done is make the door always seem open with the end stops. If I made it always closed then I had to use the PIN code too everytime I spoke to Alexa to Unlock it. Also, when I first tried your Smart Lock code, I forgot to change the type in Sinric Pro from Switch. I will give the reed switches a try this summer for sure. Will be better to be able to know what state the door is in sometimes. Thanks again :)

Dom2955774 commented 3 years ago

hi, i am having the same problem. i am new to coding and i am using arduino IDE, i am trying to get a example sketch which switches a relay on and then off after a specified time just like a momentary push button would do. i am trying to do this with sinric pro to open a door, can anyone point me in the right direction please

kakopappa commented 3 years ago

@Dom2955774 https://github.com/sinricpro/esp8266-esp32-sdk/blob/master/examples/Relay/Relay/Relay.ino If you have issues, open another issue

pedrofnm commented 2 years ago

Hi, best way to achive what you guys need just add a delay of a few miliseconds then digitalwrite the pin LOW:

      ...
      digitalWrite(relay.pin, state);  

      delay(500);

      digitalWrite(relay.pin, LOW);

      return true;    
      ...
sivar2311 commented 2 years ago

Hi @pedrofnm Please not that this issue was closed over 2 years ago.

Refering to your code: The state parameter can be false which is the same as LOW In this case your code would perform like this:

digitalWrite(relay.pin, LOW);
delay(500);
digitalWrite(relay.pin, LOW);
return true;

Waiting 500ms for nothing

Refering "a few milliseconds": A delay always blocks the whole sketch. For me (personally) a "few milliseconds" would be maximum of 10 ms. 500 ms is a half of a second where no incomming requests / outgoing events can be handled or send. So, for handling such long delays, better set a flag or a timestamp in the callback. Handle that flag/timestamp outside the callback in the loop context. Thus prevents blocking the whole sketch. That's why I always recommend to avoid using the delay function wherever you can.

bladeduypro commented 2 years ago

Thank you for your sharing. In some cases, it works for my project like switching an air conditioner. I just need to control the switch of the remote control or switch-on button instead of using a relay to control the power of the air-conditioner. Really appreciate!

kakopappa commented 2 years ago

Hi @bladeduypro

To control IR devices you need to emulate the IR signal on/off button.

Open Source: IR decoder http://www.esp32learning.com/code/esp32-and-infrared-receiver-example.php Commercial: https://irdevkit.com/

If you have any further questions, please open a new issue