Can't get physical and a digital button doing the same thing

Hi guys,

i could really use your help. i have been building a programmable catfeeder and so far it work pretty well. For now i have one blynk button to feed manually and several timed tasks and they work just fine.

I wanted to add a physical button to my feeder, but i dont get right. I have to admit, that i had absolutly no knowledge of arduinos and I would be really glad, if someone could help me out.

I want two buttons, one physical and one blynk button to feed manually and several timers.

I am using an ELEGIANT NodeMcu Lua ESP8266 ESP-12E WIFI Development Board.

Here is my code

// Cat Feeder Wifi Sketch

#include <ESP8266WiFi.h>                             //needed for the wifi connection
#include <BlynkSimpleEsp8266.h>                      //needed for the blynk application
#include <Servo.h>                                   //needed for the servos (you could also just also use only 1)
Servo myservo;


char auth[] = ;                         //here goes your blynk token
char ssid[] = ;                         //here goes your wifi SSID
char pass[] = ;                        //here goes your wifi password


const int servoPin = 14;                         //pin for the servos
int buttonPin = 3;                                   //pin for the button


#define D5 14                                        //actually you don´t have to define these,
#define D9 3                                         //but since the nodemcu pin map is kind of different,


//virtual needed pins for the timers
//you can add as much virtual pins, as you need timers (in my case, I needed 5 timers at most)
BLYNK_WRITE(V1){
  if (param.asInt()){ 
      digitalWrite(buttonPin, HIGH);
  } else {
      digitalWrite(buttonPin, LOW);
  }
}

BLYNK_WRITE(V2){
  if (param.asInt()){ 
      digitalWrite(buttonPin, HIGH);
  } else {
      digitalWrite(buttonPin, LOW);
  }
}

void setup()
{
  //this is needed for the blynk app
  Serial.begin(9600);
  Blynk.begin(auth, ssid, pass);
  

  // this is the servo setup
  pinMode(buttonPin, INPUT);
  myservo.attach(servoPin);
  myservo.write(175);
  delay(500);
  myservo.detach();
}


void loop()
{
  Blynk.run();
  
  // this is the servo loop
    int buttonVal = digitalRead(buttonPin);
    if(buttonVal == HIGH) {
      myservo.attach(servoPin);
      myservo.write(55);
      delay(500);
      myservo.write(175);
      delay(500);
      myservo.write(160);
      delay(5000);
      myservo.write(175);
      delay(450); 
      myservo.detach();
      delay(3000);
    }
  delay(13);
}

The picture of the cat just does it, that is one cute cat … you got me hooked.

First off, it’s not very smart to do anything but Blynk.run() in the loop. I see you have a lot of delays there. That is bound to be troublesome at some point.

If you check the “PushData” example of Blynk you can see an example of how to use SimpleTimer to do timed things. You should move the Servo loop to a timed running function. I’m not sure how to implement the delays, but I think with SimpleTimer we can achieve it.

I presume the Servo opens some sort of valve to allow for a certain amount of cat food to drop in the bowl? Can you show us a video of how it works? Does your code actually work? Because I’d be surprised if it’s stable with an ESP and all the delays.

-edit

Furthermore, electrical buttons have to be debounced, but there are a couple very elegant, yet small solutions for that out there, mostly with a capacitor and two resistors, so that shouldn’t be a problem.

Hi,

actually it was just one simple delay. Though i had sometimes issues with the food getting stuck and my cats were smart enough to notice it and accomplished to open the “detached” servos a bit, so that some more food came out.

My first idea was, to use the delays to let the servo try to attempt to close the gap again. It didnt work well, so i just glued two little wooden things in the opening and now they can’t mess around anymore. So actually it will be just one delay again before detaching.

So what can i do about my problem with the buttons?

I tried different things and i did get the physical button to work on its own and also the blynk button. But when i tried to apply the the blynk button to the same digital button the physical one was hooked up, it didnt work. i changed the code over and over, once it never stopped opening and closing, once the physical button didnt react.

i think it has something to do with the HIGH and LOW states. The physical button works just, when it is on LOW, and my current code with the blynk buttons just works with HIGH.

It doesn’t really matter what states the buttons (virtual or otherwise) react to. What you have to do is track the state of a button. So you’ll need an extra variable. Your problem is very similar to this: 2 way lighting circuit control with blynk and feedback updates

Have you read there? There is a lot of viable code there to solve your problem I think. (especially at the end of the topic).

actually i dont understand, why i need to track the state of the button. i wanted a more simple solution. :tired_face:

i just wanted the buttons to run the servo loop, when pressed. here is what i thought.

cant i assign the physical button to another pin and let the same servo loop happen.

lets say something as if either button 1 (phyiscal) or button 2 (blynk button) is pushed, do task “A” (the servo routine).

I corrected the code without the obsolete delays

// Cat Feeder Wifi Sketch

#include <ESP8266WiFi.h>                             //needed for the wifi connection
#include <BlynkSimpleEsp8266.h>                      //needed for the blynk application
#include <Servo.h>                                   //needed for the servos (you could also just also use only 1)
Servo myservo;


char auth[] = ;                         //here goes your blynk token
char ssid[] = ;                         //here goes your wifi SSID
char pass[] = ;                        //here goes your wifi password


const int servoPin = 14;                         //pin for the servos
int buttonPin = 3;                                   //pin for the button


#define D5 14                                        //actually you don´t have to define these,
#define D9 3                                         //but since the nodemcu pin map is kind of different,


//virtual needed pins for the timers
//you can add as much virtual pins, as you need timers (in my case, I needed 5 timers at most)
BLYNK_WRITE(V1){
  if (param.asInt()){ 
      digitalWrite(buttonPin, HIGH);
  } else {
      digitalWrite(buttonPin, LOW);
  }
}

BLYNK_WRITE(V2){
  if (param.asInt()){ 
      digitalWrite(buttonPin, HIGH);
  } else {
      digitalWrite(buttonPin, LOW);
  }
}

void setup()
{
  //this is needed for the blynk app
  Serial.begin(9600);
  Blynk.begin(auth, ssid, pass);
  

  // this is the servo setup
  pinMode(buttonPin, INPUT);
  myservo.attach(servoPin);
  myservo.write(175);
  delay(500);
  myservo.detach();
}


void loop()
{
  Blynk.run();
  
  // this is the servo loop
    int buttonVal = digitalRead(buttonPin);
    if(buttonVal == HIGH) {
      myservo.attach(servoPin);
      myservo.write(55);
      delay(500);
      myservo.write(175);
      delay(500);
      myservo.detach();
      delay(3000);
    }
}

Yeah, that’s possible.

You can write your own function. E.g.

BLYNK_WRITE(V1)
{
 if(param.asInt() )
 {
  doServoStuff();
 }
}

void loop()
{
 if(digitalRead(1) == HIGH)
 {
    doServoStuff();
 }
}

void doServoStuff()
{
// do stuff here
}

Mind you, it’s bad practice to do this in the loop() part! You should use a simple timer for this. but it could work.

-edit

There are still delays in your code, you need to get rid of them using SimpleTimer :slight_smile:

Wololooo…
This is now a cat thread

Don’t get me started, we got five … and about a gazilion pics of each, lmao.

-edit

and if that one is really yours I want it, it’s really cute :smiley:

1 Like

So besides that i have to get into the SimpleTimer stuff…

it could work like this?

const int servoPin = 1;
int virtualbuttonPin = 2;
int physicalbuttonPin = 3; 

 
void setup()
{
  Serial.begin(9600);
  Blynk.begin(auth, ssid, pass);
  pinMode(virtualbuttonPin, INPUT);
  pinMode(physicalbuttonPin, INPUT);
  myservo.attach(servoPin);
  myservo.write(175);
  delay(500);
  myservo.detach();
}


BLYNK_WRITE(V1){
  if (param.asInt()){ 
      digitalWrite(virtualbuttonPin, HIGH);
      myservo.attach(servoPin);
      myservo.write(55);
      delay(500);
      myservo.write(175);
      delay(500);
      myservo.detach();
      delay(3000);
  }
}

void loop()
{
  Blynk.run();
  
  // this is the servo loop
    int buttonVal = digitalRead(physicalbuttonPin);
    if(buttonVal == HIGH) {
      myservo.attach(servoPin);
      myservo.write(55);
      delay(500);
      myservo.write(175);
      delay(500);
      myservo.detach();
      delay(3000);
    }
}

Here is my other one :smiley:

Throwing my dogs in here for good measure :stuck_out_tongue:

Also @p3pe never use delay() … ever

You need to convert the following to a new function and use a SimpleTimer setTimeout function.

// this is the servo loop
    int buttonVal = digitalRead(physicalbuttonPin);
    if(buttonVal == HIGH) {
      myservo.attach(servoPin);
      myservo.write(55);
      delay(500);
      myservo.write(175);
      delay(500);
      myservo.detach();
      delay(3000);
    }

int buttonValPrev;

void loop(){
  button();
}

void button(){
  int buttonVal = digitalRead(physicalbuttonPin);

  if(buttonVal == HIGH && buttonValPrev == LOW) { 
    // button pressed in, will stop the function looping
    buttonValPrev = buttonVal; // stop a function loop

    myservo.attach(servoPin);
    myservo.write(55);
    timer.setTimeout(500, servoStage1); // delay 500ms then do servoStage1
    
  }
}

void servoStage1(){
  myservo.write(175);
  timer.setTimeout(500, servoStage2); // delay 500ms then do servoStage2
}

void servoStage2(){
  myservo.detach();
}

I had some code to contribute, but my mouse is acting up and I couldn’t post it :slight_smile:

2 Likes

@Jamin is showing what I’d thought of but hadn’t put to paper yet, sort of speak.

I like the Britishshorthair! Your other one has a somewhat oriental look to it (we own a couple Siamese and an OSH).

but that’s another matter entirely :smiley:

I’d try @Jamin his code. You could add a debounced physical button using a capacitor and a couple resistors to prevent accidental overfeeding

1 Like

Baby Naala says:

We need a sticky thread on the forum detailing the basics

  • always format code for forum posts
  • never use delays in you sketch
  • learn SimpleTimer
  • read blynk docs thoroughly before asking for help
  • always provide HW used, questions and code in first post neatly structured
  • optional for @Lichtsignaal, provide cat picture

What does your inner cat say @Dmitriy, can we get a sticky :wink:

Way off topic, but I’ll indulge your curiosity (which, as we all know, killed the cat, but contempment brought it back :wink: )

-edit this one is called Pavel b.t.w. …

1 Like

Will all cat affectionados please stand up :smiley:

I trained BeBe to “sit pretty” for treats

Hey guys. First of all. Thanks for the very fast help. I really appreciate it! Especially because I am so very new to this world. Maybe I shouldn’t have started with a “sophisticated” project like this. But here I am… lucky me, the stand alone blynk button version worked from the beginning, as also my construction itself.

And although the new code is not my work, I already learned a lot by just looking at what you sent me. This is really encouraging.

For instance did I not yet ran into the problem false interrupts and I just learned about software and hardware debouncing. Although this has nothing to do with my code, I wanted to ask you, if I need this inverted schmitt trigger or if it could be done with a couple of resistors, the capacitor and a simple button.

Besides that I was looking at the code provided by Jamin and he very kindly changed the delays. So I tried to understand the logic behind it and to complete my code. It now looks like that and I wanted you to tell me, if this should work. I can’t really test it, because due to my work I am not at home for another week. I hope its going in the right way at least.

So here it is:

Thx again!

// Cat Feeder Wifi Sketch

#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>
#include <SimpleTimer.h>
#include <Time.h>
#include <Servo.h>

char auth[] = ;
char ssid[] = ;
char pass[] = ;

const int servoPin = 1;
int physicalbuttonPin = 2;
int virtualbuttonPin = 3;
int buttonValPrev;


BLYNK_WRITE(V1){
  if (param.asInt()){ 
      digitalWrite(virtualbuttonPin, HIGH);
  } else {
      digitalWrite(virtualbuttonPin, LOW);
  }
}

void setup(){
  Serial.begin(9600);
  Blynk.begin(auth, ssid, pass);
  pinMode(physicalbuttonPin, INPUT);
  pinMode(virtualbuttonPin, INPUT);
}


void loop(){
  Blynk.run();
  timer.run();
  physicalbutton();
  virtualbutton();
}


void physicalbutton(){
  int buttonVal = digitalRead(physicalbuttonPin);

  if(buttonVal == HIGH && buttonValPrev == LOW) { 
    buttonValPrev = buttonVal;
    myservo.attach(servoPin);
    myservo.write(55);
    timer.setTimeout(500, servoStage1);
  }
}

void virtualbutton(){
  int buttonVal = digitalRead(virtualbuttonPin);

  if(buttonVal == HIGH && buttonValPrev == LOW) { 
    buttonValPrev = buttonVal;
    myservo.attach(servoPin);
    myservo.write(55);
    timer.setTimeout(500, servoStage1);
  }
}

void servoStage1(){
  myservo.write(175);
  timer.setTimeout(500, servoStage2); // delay 500ms then do servoStage2
}

void servoStage2(){
  myservo.detach();
}

did it works ?

Don’t waste your time with this code, it’d very badly written.

Pete.