homieiot / homie-esp8266

💡 ESP8266 framework for Homie, a lightweight MQTT convention for the IoT
http://homieiot.github.io/homie-esp8266
MIT License
1.36k stars 308 forks source link

delay not working? #311

Closed koen01 closed 7 years ago

koen01 commented 7 years ago

why is the delay not working in this code? the servo moves at the same speed as without the delay. Using the standard esp servo sweep example i can slow down the servo...but when i use it with homie-esp8266 it doesn't work anymore?

#include <Homie.h>
#include <Servo.h>

// create servo object to control a servo
Servo myservo;
// create a servo node that listens to servo/degrees/set
HomieNode servoNode("servo", "degrees");

// setup some variables
int degrees = 0 ;
int new_degrees;

bool degreeHandler(const HomieRange& range, const String& value) {
  int new_degrees = value.toInt();
  if (new_degrees < 0 || new_degrees > 170) return false;
  else if (new_degrees > degrees)
    for (new_degrees = value.toInt(); degrees <= new_degrees; degrees += 1) {
      myservo.write(degrees);
      Homie.getLogger() << "Degrees " << (degrees) << endl;
      delay(255);
    }
  else {
    for (new_degrees = value.toInt(); degrees >= new_degrees; degrees -= 1) {
      myservo.write(degrees);
      Homie.getLogger() << "Degrees " << (degrees) << endl;
      delay(255);
    }
    servoNode.setProperty("degrees").send(value);
    Homie.getLogger() << "Degrees " << (degrees) << endl;
    degrees = new_degrees;
    return true;
  }
}

void setup() {
  Serial.begin(115200);
  Serial << endl << endl;
  myservo.attach(D8);  // attaches the servo on D8 to the servo object
  myservo.write(0);
  Homie_setFirmware("awesome-servo", "1.0.0");

  servoNode.advertise("degrees").settable(degreeHandler);

  Homie.setup();
}

void loop() {
  Homie.loop();
}
euphi commented 7 years ago

You shall not call delay within any Homie callback or loop(), as this will block Homie functions.

The way to proceed is to set a "target" degrees globally (and store the current degress globally) and then to check every 255ms inside the loop() if the current degrees have reached the target degrees and if not increase (or decrease) the current degrees and send them to your servo lib.

If you need more complex control functions I suggest to have a look at the great "Automaton" library (https://github.com/tinkerspy/Automaton) - there is also a servo extension at https://github.com/tinkerspy/Automaton-Servo

marvinroger commented 7 years ago

@koen01 as @euphi said, you can't call any delay or yield in Homie functions because Homie works in the "background". The solution is to use what @euphi said (see http://playground.arduino.cc/Code/AvoidDelay)

marcolino7 commented 5 years ago

Hi, in my sketch, in a Handler i need to simulate a pushbutton press with a relè, for this i need to set an Output to High for 1 second and then back to Low. How can achieve this without delay?

Thanks

echedev commented 5 years ago

@marcolino7 Use can use timer. When you set to High you save current value of millis(). Then in the loop() you check if the current timer value exceed your saved value more that 1 second (or any delay you need), you set output to Low.

marcolino7 commented 5 years ago

@marcolino7 Use can use timer. When you set to High you save current value of millis(). Then in the loop() you check if the current timer value exceed your saved value more that 1 second (or any delay you need), you set output to Low.

Done Thanks