Virtual Pin problem

I understand the code below may be somewhat confusing and take time to understand, but I am focused on the virtual pins V40 and V41. The other virtual pins all seem to work as intended…

Not sure why when I adjust V40 or V41 that “singleserve” and multiserve" don’t seem to change (the resulting loop count of the if statements doesn’t seem to change. These values are meant to adjust “portions” so the loop count for distrubute() can be changed using my mobile. However all other virtual pins seem to function as expected… Little confused why.

#include <Servo.h>

// esp initialise

/* Comment this out to disable prints and save space */
#define BLYNK_PRINT Serial


#include <ESP8266_Lib.h>
#include <BlynkSimpleShieldEsp8266.h>

// You should get Auth Token in the Blynk App.
// Go to the Project Settings (nut icon).
char auth[] = "###############";

// Your WiFi credentials.
// Set password to "" for open networks.
char ssid[] = "###########";
char pass[] = "########";

// Hardware Serial on Mega, Leonardo, Micro...
#define EspSerial Serial

// Your ESP8266 baud rate:
#define ESP8266_BAUD 9600

ESP8266 wifi(&EspSerial);

// Declare the Variables

int durationDown;
int durationUp;

//pins for input switches
int pushButtonPin = 4; // push button pin input
int pedalButtonPin = 5;  // pedal button pin input

// pins for outputs of LED and servo
int servoPin = 9; // servo pin output
int ledpin = 10; // led in box output
int timerexceedpin =  8; //led pin to say duration exceed

//variable define
int pushButtonState = 0; // box button state
// int portions = 5; // assign 5x portions as default, although all cases have their own value
int portionCount = 0; // the counter for how many portions (loops) have been given in this time
int pedalButtonState = 0; // pedal button state
int virtualpin1 = 0; // virtual pin for 1x feed
int virtualpin5 = 0; // virtual pin for 5x feed
// virtual pin V10 for indicator in app is defined below
int fill = 70;
int empty = 120;
int multiserve = 7;
int singleserve = 1;
int portions = singleserve;
int timermet = 0; // timer start time met = 1
int timeron = 0; // timer on = 1

//timer define variables
unsigned long startOfDay = 0; // days lapsed in milliseconds
unsigned long awholeday = 86400000; // increment for startofday and also to check if less than a day
int timesPressed = 0; // count how many times pushed in 1 day
unsigned long lastPress = millis(); // last press in milliseconds;
unsigned long timerduration = 10800000; // duration in millseconds to count to
unsigned long distributeperday = 4; // distribute limit per day

// Blynk virtual pin routine and assign to variables
BLYNK_WRITE(V1)
{
  int pinValue = param.asInt(); // assigning incoming value from pin V1 to a variable
  virtualpin1 = pinValue;
}

BLYNK_WRITE(V5)
{
  int pinValue = param.asInt(); // read incoming value from pin V5
  virtualpin5 = pinValue; // assign pin value to its own variable
}

BLYNK_WRITE(V20)  // target duration down
{
  durationDown = param.asInt();
  if (durationDown == 1) {
    durationDownFunc();
  }
}

BLYNK_WRITE(V21) // target duration up
{
  durationUp = param.asInt();
  if (durationUp == 1) {
    durationUpFunc();
  }
}
void durationDownFunc()
{
  timerduration = timerduration - 600000;
  unsigned int hours = timerduration / 3600000; //max value of hours = 65535
  unsigned int minutes = (timerduration - 3600000 * hours) / 60000;
  Blynk.virtualWrite(V22, hours);
  Blynk.virtualWrite(V23, minutes);
}
void durationUpFunc()
{
  timerduration = timerduration + 600000;
  unsigned int hours = timerduration / 3600000; //max value of hours = 65535
  unsigned int minutes = (timerduration - 3600000 * hours) / 60000;
  Blynk.virtualWrite(V22, hours);
  Blynk.virtualWrite(V23, minutes);
}

BLYNK_WRITE(V24) // distribution per day
{
  int pinValue = param.asInt();
  distributeperday = pinValue;
}

BLYNK_WRITE(V30) // fill angle
{

  int pinValue = param.asInt();
  fill = pinValue;
}

BLYNK_WRITE(V31) // empty angle
{
  int pinValue = param.asInt();
  empty = pinValue;
}

BLYNK_WRITE(V40) // dispense amount small
{
  int pinValue = param.asInt();
  singleserve = pinValue;
}

BLYNK_WRITE(V41) // dispense amount large
{
  int pinValue = param.asInt();
  multiserve = pinValue;
}

BLYNK_WRITE(V50)
{
  int pinValue = param.asInt(); // read incoming value from pin V50
  timermet = pinValue; // assign pin value to its own variable
  if (timermet == 1)
  {
    if (timeron == 1);
    {
      portions = multiserve;
      distribute();
    }
  }
}

BLYNK_WRITE(V51)
{
  int pinValue = param.asInt(); // read incoming value from pin V5
  timeron = pinValue; // assign pin value to its own variable
}

// Create a servo object Servo1
Servo Servo1;

void setup()
{
  digitalWrite(timerexceedpin, HIGH);
  // esp and blynk setup

  // Debug console
  Serial.begin(9600);
  delay(10);
  EspSerial.begin(ESP8266_BAUD); // Set ESP8266 baud rate
  delay(10);

  Blynk.begin(auth, wifi, ssid, pass);

  // initialize the digital pins as outputs or inputs:
  pinMode(pushButtonPin, INPUT); // serving switch
  pinMode(servoPin, OUTPUT); // servo control pin
  pinMode(ledpin, OUTPUT); // box led switch
  pinMode(13, OUTPUT);  // onboard led switch
}

void loop()
{

  //blynk loop

  Blynk.run();

  //read digital switch pins
  pushButtonState = digitalRead(pushButtonPin); // read push button switch
  pedalButtonState = digitalRead(pedalButtonPin); // read pedal switch

  // virtual pins

  if (virtualpin1 == 1)
  {
    portions = singleserve;
    Blynk.virtualWrite(V10, "Reilly is Fed");
    distribute();
    Blynk.virtualWrite(V10, " ");
  }

  if (virtualpin5 == 1)
  {
    portions = multiserve;
    Blynk.virtualWrite(V10, "Reilly is Fed");
    distribute();
    Blynk.virtualWrite(V10, " ");
  }


  // box buttton pushed
  if (pushButtonState == 1)
  {
    delay(1000);
    pushButtonState = digitalRead(pushButtonPin);
    if (pushButtonState == 0)
    {
      portions = singleserve;
      distribute();
    }
    else
    {
      portions = multiserve;
      distribute();
    }
  }


  if ( millis() - startOfDay >= awholeday ) // this part is maybe better done with an RTC
  {
    startOfDay += awholeday;
    timesPressed = 0;
  }

  if (millis() < awholeday)
  {
    startOfDay = 0;
  }

  if (( pedalButtonState == 1 ) && ( timesPressed < distributeperday ) && ( millis() - lastPress >= timerduration )) // pedal pushed and less than allowance
  {

    portions = singleserve;
    distribute();
    digitalWrite(timerexceedpin, LOW);
    Blynk.email("##########", "Reilly pushed the button", "Clever Boy");
    lastPress = millis();
    timesPressed++;
  }

  if (( pedalButtonState == 1 ) && (( timesPressed >= distributeperday || millis() - lastPress  < timerduration))) // pedal pushed when no LED notifcation
  {
    Blynk.email("###########", "Reilly impatiently pushed the button", "Hungry Boy");
  }

  if (( millis() - lastPress >= timerduration ) && ( timesPressed < distributeperday )) // time passed and under allowance to turn light on
  {
    digitalWrite(timerexceedpin, HIGH);
  }

} // loop bracket


// distribute function that is called from above. Portion size or loops is determined from the cases above. Turn box led on to see levels
void distribute()
{
  Servo1.attach(servoPin); // attach servo to pin and closed loop
  digitalWrite(ledpin, HIGH);  // turn led on in box
  Servo1.write(fill); // Make servo go to 0 degrees for startup
  delay(1000);
  while (portionCount < portions)
  {
    portionCount = portionCount + 1; //itertae portion count
    Servo1.write(empty); // Make servo go to 100 degrees
    delay(1000);
    Servo1.write(fill); // Make servo go to 0 degrees
    delay(1000);
  }
  Servo1.detach(); //removes control of servo to save power of closed loop
  portionCount = 0; // reset portion count
  digitalWrite(ledpin, LOW); // turn box led off
}

I guess without having to read and understand all of my sketch, searching term “singleserve”, “multiserve” and “portions” will show all the code that doesn’t appear to function as expected.

I should note that “portions” seems to stay as per defined in the variables section on booting, so doesn’t update when the virtual pins are changed in my android app. The other virtual pins work as expected.

Messy code @Pete_Repeat you don’t need all the pinValue entries. If you are using the variable elsewhere just define it as a global variable. loop() is bad.
I think the problem with V40 and V41 is that it updates single /multi serve but not portions. Unless you can point out how V40 and V41 are linked to the portions update part of the code.

Why not include a function call in V40 / V41 to portions update?

The portions are defined in various cases in the loop().

The “if (virtualpin1 ==1)” statement makes portions =singleserve & the “if (virtualpin5 == 1)” statement makes portions = multiserve.

The two cases are so I can trigger different serving portions.

In loop() there are also physical button pushes that distribute singleserve and multiserve.

Yes but is virtualpin1 / 5 actually 1 because they are initially defined as 0?

loop() is a very bad place for all that stuff. I don’t know what other parts of your code use the virtualpin1 / 5 in loop but for V40 / V41 I suggest:

void portionSize(){
  if (virtualpin1 == 1)
  {
    portions = singleserve;
    Blynk.virtualWrite(V10, "Reilly is Fed");
    distribute();
    Blynk.virtualWrite(V10, " ");
  }

  if (virtualpin5 == 1)
  {
    portions = multiserve;
    Blynk.virtualWrite(V10, "Reilly is Fed");
    distribute();
    Blynk.virtualWrite(V10, " ");
  }
}

BLYNK_WRITE(V40) // dispense amount small
{
  singleserve = param.asInt();
  portionSize();
}

BLYNK_WRITE(V41) // dispense amount large
{
  multiserve = param.asInt();
  portionSize();
}

This assumes virtualpin1 / 5 are actually set to the correct state of 1. You could also just use a single variable (0 is small portion and 1 is large portion rather than the 2 variables you currently have). It can then be an if else statement.

Thanks for the feedback. I’m slowly learning and have edited my code. I hope it works when I can upload it to the arduino in the next day or two… I will upload it here, but don’t expect you to spend too much time looking at it seeing I haven’t debugged it myself at all (other than compile).

No other parts use virtualpin1 / 5.

I have now removed both the “if virtualpin#” out of the loop() and moved the contents of that into the top section (in the respective Blynk_write sections).

I realised the Blynk_write parts aren’t meant to go into the loop() but hadn’t realised it was not good practice even having the if (virtualpin1) in the loop ()… They are now moved though so any reference to the virtual pins (including any global variables that equal the pins values) are outside the loop(). Pretty much only the usual arduino bits like digitalread etc are in the loop() now.

I have now separated the distrubute() function into 2 separate functions called distributesingle() and distributemulti() and removed portions variable. The blynk virtualpin1 calls the distributesingle() and the virtualpin5 calls the distributemulti(), with the physical button brief push calling distributesingle() and long push calls distributemulti()…

I know I might not be explaining it clearly but if it doesn’t work still I will try report back more clearly with what I have done.

#include <Servo.h>

// esp initialise

/* Comment this out to disable prints and save space */
#define BLYNK_PRINT Serial


#include <ESP8266_Lib.h>
#include <BlynkSimpleShieldEsp8266.h>

// You should get Auth Token in the Blynk App.
// Go to the Project Settings (nut icon).
char auth[] = "###";

// Your WiFi credentials.
// Set password to "" for open networks.
char ssid[] = "###";
char pass[] = "#####";

// Hardware Serial on Mega, Leonardo, Micro...
#define EspSerial Serial

// Your ESP8266 baud rate:
#define ESP8266_BAUD 9600

ESP8266 wifi(&EspSerial);

// Declare the Variables

int durationDown;
int durationUp;

//pins for input switches
int pushButtonPin = 4; // push button pin input
int pedalButtonPin = 5;  // pedal button pin input

// pins for outputs of LED and servo
int servoPin = 9; // servo pin output
int ledpin = 10; // led in box output
int timerexceedpin =  8; //led pin to say duration exceed

//variable define
int pushButtonState = 0; // box button state
int portionCount = 0; // the counter for how many portions (loops) have been given in this time
int pedalButtonState = 0; // pedal button state
int virtualpin1 = 0; // virtual pin for 1x feed
int virtualpin5 = 0; // virtual pin for 5x feed
// virtual pin V10 for indicator in app is defined below
int fill = 70;
int empty = 120;
int multiserve = 7;
int singleserve = 1;
int timermet = 0; // timer start time met = 1
int timeron = 0; // timer on = 1
int timerondiff = 0; // block to stop the timed feeding to stop looping while the time period is met
int timeronold = 0; // value that is only a value of 1 for the first time feeding loop

//timer define variables
unsigned long startOfDay = 0; // days lapsed in milliseconds
unsigned long awholeday = 86400000; // increment for startofday and also to check if less than a day
int timesPressed = 0; // count how many times pushed in 1 day
unsigned long lastPress = millis(); // last press in milliseconds;
unsigned long timerduration = 10800000; // duration in millseconds to count to
unsigned long distributeperday = 4; // distribute limit per day

// Blynk virtual pin routine and assign to variables
BLYNK_WRITE(V1)
{
  int virtualpin1 = param.asInt(); // assigning incoming value from pin V1 to a variable
  if (virtualpin1 == 1)
  {
    Blynk.virtualWrite(V10, "Reilly is Fed");
    distributesingle();
    Blynk.virtualWrite(V10, " ");
  }
}

BLYNK_WRITE(V5)
{
  int virtualpin5 = param.asInt(); // read incoming value from pin V5
  if (virtualpin5 == 1)
  {
    Blynk.virtualWrite(V10, "Reilly is Fed");
    distributemulti();
    Blynk.virtualWrite(V10, " ");
  }
}

BLYNK_WRITE(V20)  // target duration down
{
  durationDown = param.asInt();
  if (durationDown == 1)
  {
    durationDownFunc();
  }
}

BLYNK_WRITE(V21) // target duration up
{
  durationUp = param.asInt();
  if (durationUp == 1)
  {
    durationUpFunc();
  }
}
void durationDownFunc()
{
  timerduration = timerduration - 600000;
  unsigned int hours = timerduration / 3600000; //max value of hours = 65535
  unsigned int minutes = (timerduration - 3600000 * hours) / 60000;
  Blynk.virtualWrite(V22, hours);
  Blynk.virtualWrite(V23, minutes);
}

void durationUpFunc()
{
  timerduration = timerduration + 600000;
  unsigned int hours = timerduration / 3600000; //max value of hours = 65535
  unsigned int minutes = (timerduration - 3600000 * hours) / 60000;
  Blynk.virtualWrite(V22, hours);
  Blynk.virtualWrite(V23, minutes);
}

BLYNK_WRITE(V24) // distribution per day
{
  int distributeperday = param.asInt();
}

BLYNK_WRITE(V30) // fill angle
{
  int fill = param.asInt();
}

BLYNK_WRITE(V31) // empty angle
{
  int empty = param.asInt();
}

BLYNK_WRITE(V40) // dispense amount small
{
  int singleserve = param.asInt();
}


BLYNK_WRITE(V41) // dispense amount large
{
  int multiserve = param.asInt();
}

BLYNK_WRITE(V50) // defined time to feed
{
  int pinValue = param.asInt(); // read incoming value from pin V50
  timermet = pinValue; // assign pin value to its own variable
  if (timermet == 1) // if timer time is met
  {
    if (timeron == 1); // if timer is turned on
    {
      timerondiff = 1 - timeronold;
      if (timerondiff == 1) // this makes it run only on change of 0 to 1
      {
        timeronold = 1;
        distributemulti();
      }
    }
  }
  else
  {
    timeronold = 0;
  }
}

BLYNK_WRITE(V51) // is timed feed on
{
  int pinValue = param.asInt(); // read incoming value from pin V5
  timeron = pinValue; // assign pin value to its own variable
}

// Create a servo object Servo1
Servo Servo1;

void setup()
{
  digitalWrite(timerexceedpin, HIGH);
  // esp and blynk setup

  // Debug console
  Serial.begin(9600);
  delay(10);
  EspSerial.begin(ESP8266_BAUD); // Set ESP8266 baud rate
  delay(10);

  Blynk.begin(auth, wifi, ssid, pass);

  // initialize the digital pins as outputs or inputs:
  pinMode(pushButtonPin, INPUT); // serving switch
  pinMode(servoPin, OUTPUT); // servo control pin
  pinMode(ledpin, OUTPUT); // box led switch
  pinMode(13, OUTPUT);  // onboard led switch
}

void loop()
{

  //blynk loop

  Blynk.run();

  //read digital switch pins
  pushButtonState = digitalRead(pushButtonPin); // read push button switch
  pedalButtonState = digitalRead(pedalButtonPin); // read pedal switch

  // box buttton pushed
  if (pushButtonState == 1)
  {
    delay(1000);
    pushButtonState = digitalRead(pushButtonPin);
    if (pushButtonState == 0)
    {
      distributesingle();
    }
    else
    {
      distributemulti();
    }
  }


  if ( millis() - startOfDay >= awholeday ) // this part is maybe better done with an RTC
  {
    startOfDay += awholeday;
    timesPressed = 0;
  }

  if (millis() < awholeday)
  {
    startOfDay = 0;
  }

  if (( pedalButtonState == 1 ) && ( timesPressed < distributeperday ) && ( millis() - lastPress >= timerduration )) // pedal pushed and less than allowance
  {

    distributesingle();
    digitalWrite(timerexceedpin, LOW);
    Blynk.email("####", "Reilly pushed the button", "Clever Boy");
    lastPress = millis();
    timesPressed++;
  }

  if (( pedalButtonState == 1 ) && (( timesPressed >= distributeperday || millis() - lastPress  < timerduration))) // pedal pushed when no LED notifcation
  {
    Blynk.email("######", "Reilly impatiently pushed the button", "Hungry Boy");
  }

  if (( millis() - lastPress >= timerduration ) && ( timesPressed < distributeperday )) // time passed and under allowance to turn light on
  {
    digitalWrite(timerexceedpin, HIGH);
  }

} // loop bracket


// distribute function that is called from above. Portion size or loops is determined from the cases above. Turn box led on to see levels
void distributesingle()
{
  Servo1.attach(servoPin); // attach servo to pin and closed loop
  digitalWrite(ledpin, HIGH);  // turn led on in box
  Servo1.write(fill); // Make servo go to 0 degrees for startup
  delay(1000);
  while (portionCount < singleserve)
  {
    portionCount = portionCount + 1; //itertae portion count
    Servo1.write(empty); // Make servo go to 100 degrees
    delay(1000);
    Servo1.write(fill); // Make servo go to 0 degrees
    delay(1000);
  }
  Servo1.detach(); //removes control of servo to save power of closed loop
  portionCount = 0; // reset portion count
  digitalWrite(ledpin, LOW); // turn box led off
}

void distributemulti()
{
  Servo1.attach(servoPin); // attach servo to pin and closed loop
  digitalWrite(ledpin, HIGH);  // turn led on in box
  Servo1.write(fill); // Make servo go to 0 degrees for startup
  delay(1000);
  while (portionCount < multiserve)
  {
    portionCount = portionCount + 1; //itertae portion count
    Servo1.write(empty); // Make servo go to 100 degrees
    delay(1000);
    Servo1.write(fill); // Make servo go to 0 degrees
    delay(1000);
  }
  Servo1.detach(); //removes control of servo to save power of closed loop
  portionCount = 0; // reset portion count
  digitalWrite(ledpin, LOW); // turn box led off
}

I understand and I basically rewrote your code in a similar way. I can’t test it as I don’t have any nasty shield configurations set up at present.

Until you become experienced then we normally say 2 lines of code in loop() is the recommended maximum, like so:

void loop()
{
  if (Blynk.connected()) {Blynk.run();}
  timer.run();
}

You really need to study Blynk.timer which is a rename of Arduino’s SimpleTimer and calls functions at intervals. Despite the new name it’s not a Blynk function and will run with / without an internet connection.
Also attachInterrupt() is the best way to go for trapping physical button presses.

I have taken your suggestion about Blynk.timer in. It was on the cards for me once I get this running properly as it will get rig of the delay() statements I believe and control the frequency of functions.

However I am still having problems so its on the todo list at the moment.

I have copied the relevant parts of my code (there are physical button pushes, a timer and a few other bits I omitted to make it more concise for the problem so if someone wants to compile it I can upload the full code).

Problem I have is that singleserve and multiserve stay the same value from power on/boot.

If I change V40 or V41 it doesn’t change how many times the while loop runs in the distributesingle() and distributemulti() functions. They still loop 1 time and 7 times when I push the V1 and V5 respectively.

WHy aren’t singleserve and multiserve being updated?

One way I was thinking of debugging is to send the values of singleserve sent back to the Blynk app or removing the blynk wifi parts so I can debug with the arduino ide (that is a slight hassle but not off the cards if no suggestions are given here).

I know the code could be re-written better. But I had hoped to get this working like it is as it seems so close…

int multiserve = 7;
int singleserve = 1;
int virtualpin1 = 0; // virtual pin for 1x feed
int virtualpin5 = 0; // virtual pin for 5x feed
int multiserve = 7;
int singleserve = 1;

BLYNK_WRITE(V1)
{
  int virtualpin1 = param.asInt(); // assigning incoming value from pin V1 to a variable
  if (virtualpin1 == 1)
  {
    Blynk.virtualWrite(V10, "Reilly is Fed");
    distributesingle();
    Blynk.virtualWrite(V10, " ");
  }
}

BLYNK_WRITE(V5)
{
  int virtualpin5 = param.asInt(); // read incoming value from pin V5
  if (virtualpin5 == 1)
  {
    Blynk.virtualWrite(V10, "Reilly is Fed");
    distributemulti();
    Blynk.virtualWrite(V10, " ");
  }
}

BLYNK_WRITE(V40) // dispense amount small
{
  int singleserve = param.asInt();
}


BLYNK_WRITE(V41) // dispense amount large
{
  int multiserve = param.asInt();
}


void loop() {
  // put your main code here, to run repeatedly:
  Blynk.run();
}

// distribute function that is called from above. Portion size or loops is determined from the cases above. Turn box led on to see levels
void distributesingle()
{
  Servo1.attach(servoPin); // attach servo to pin and closed loop
  digitalWrite(ledpin, HIGH);  // turn led on in box
  Servo1.write(fill); // Make servo go to 0 degrees for startup
  delay(1000);
  while (portionCount < singleserve)
  {
    portionCount = portionCount + 1; //itertae portion count
    Servo1.write(empty); // Make servo go to 100 degrees
    delay(1000);
    Servo1.write(fill); // Make servo go to 0 degrees
    delay(1000);
  }
  Servo1.detach(); //removes control of servo to save power of closed loop
  portionCount = 0; // reset portion count
  digitalWrite(ledpin, LOW); // turn box led off
}

void distributemulti()
{
  Servo1.attach(servoPin); // attach servo to pin and closed loop
  digitalWrite(ledpin, HIGH);  // turn led on in box
  Servo1.write(fill); // Make servo go to 0 degrees for startup
  delay(1000);
  while (portionCount < multiserve)
  {
    portionCount = portionCount + 1; //itertae portion count
    Servo1.write(empty); // Make servo go to 100 degrees
    delay(1000);
    Servo1.write(fill); // Make servo go to 0 degrees
    delay(1000);
  }
  Servo1.detach(); //removes control of servo to save power of closed loop
  portionCount = 0; // reset portion count
  digitalWrite(ledpin, LOW); // turn box led off
}

@Pete_Repeat I will check your code later but this is screaming out for a single for loop not two while loops.

unsigned int servings = 1;  // 1 or 7 from button

void feedthepet(){
  for(int i = 0; i <= servings; i++){
    // your motor code here but not with delay() 
  }
}

The 2 second delay in your current code will become 14 seconds when servings == 7 and this will generally get you booted off the server as you will miss the heartbeat.

Need to use BlynkTimer to repeat the motor movement x times determined by servings.

@Pete_Repeat I don’t really see anything wrong with the while loop and I tested it with this more concise code. I have set up a button on V10 with label for off as “One” and “Seven” for on.
I’ll show you the Serial Monitor first and you will see I was kicked off the server for missing the heartbeat a few times. It depends where in the heartbeat cycle you are when you select the 7 servings which takes 15 seconds (1s + (7 * 2s)). Heartbeat is every 10s with a 5s grace period which is exactly the duration your function needs as it’s currently written.

The dirty hack is to include Blynk.run() in the function and you don’t need the first 1000ms delay. A much better way is with http://playground.arduino.cc/Code/SimpleTimer and known as BlynkTimer by Blynkers.

[5162] Connecting to GargoyleTest
[6163] Connected to WiFi
[6163] IP: 192.168.10.100
[6163] 
    ___  __          __
   / _ )/ /_ _____  / /__
  / _  / / // / _ \/  '_/
 /____/_/\_, /_//_/_/\_\
        /___/ v0.4.8 on Arduino

[6169] Connecting to blynk-cloud.com:8442
[6461] Ready (ping: 84ms).
1
2
3
4
5
6
7
While loop finished
[70402] Connecting to blynk-cloud.com:8442
[70649] Ready (ping: 89ms).
1
While loop finished
1
2
3
4
5
6
7
While loop finished
1
While loop finished
1
2
3
4
5
6
7
While loop finished
1
While loop finished
1
2
3
4
5
6
7
While loop finished
[250617] Connecting to blynk-cloud.com:8442
[250773] Ready (ping: 80ms).

Modified my sketch and with the Blynk.run() in the while loop it is running fine, over and over again between 1 and 7 servings, without server (no pun intended) disconnects. No disconnects in continuous operation for 15 minutes. That’s with WeMos standalone not the lottery connection method.

unsigned int portionCount = 0;  // while loop counter
unsigned int servings = 1;    // multiserve was a bad name so changed to servings

BLYNK_WRITE(V10){
  if(param.asInt()){
    servings = 7;
  }
  else{
    servings = 1;  
  }
  feedthepet();
}

void feedthepet(){
  // delay(1000); // not needed
  //Blynk.run();    // not good enough, included in while loop
  while (portionCount < servings)    // 1 or 7 for # of portions
  {
    //portionCount = portionCount + 1; //itertae portion count
    portionCount++;   // this is where the name C++ comes from
    // motor stuff
    delay(1000);
    // motor stuff
    delay(1000);
    Serial.println(portionCount);
    Blynk.run();
  }
  portionCount = 0; // reset portion count
  Serial.println("While loop finished");
  
  if(servings == 7){    // saves me having to keep pressing a button during debugging
    Blynk.virtualWrite(V10, 0);
  }
  else{
    Blynk.virtualWrite(V10, 1);  
  }
  Blynk.syncVirtual(V10);
}

Hmm. This is why I am pulling my hair out wondering why my virtual pins aren’t changing the singleserve and multiserve…

Originally I had just a single distribute() and had a variable called portions that’s value was "meant to change by singeserve = portions. That didn’t work so I changed to two separate functions to see if that helped.

Looks like I might rewrite my code as per your suggestions and hopefully that will iron out the bug.

Question: Should I use a for condition between the values or while loop up to a certain value?

I prefer for loops.

I was thinking during the day and I might know what your problem is.

Will check and advise further.

Ooh I hope so. I might hold of writing the sketch again until you get a chance to check.

You’ve got me determined to redo my code now I understand more about Arduino and Blynk, utlising if conditions instead of while loops, Blynk.timers and also less in the loop()

What are V1, V5, V40 and V41?
If buttons, push or switch mode?
I think your problem might be that you are going through more stags than you need to and not doing virtualWrite() between the stages. I will check when I know exactly what those 4 widgets are.

V1 and V5 are push buttons (momentary) to trigger trhe release of the food. V40 and V41 are sliders that send the serve value on release.

Why 2 sliders and what max and min do you have for each?

V40 slider from 1 - 4 for the single serve (it should be labelled small serve)

V41 slider from 4-8 for multi serve.

V40 gets used for the distribution when he pushes a physical foot button himself (time limited), when I feed him myself at night time (small serve on top of his wet food) and when I feel he deserves a treat while I am at owrk.

V41 will get used when we are away for a single night or weekend away when he needs a full meal.

IN case you were worried, this is not replacing me feeding him nor is it replacing the need for someone to come over when we are on extended holidays.

If I slide V40 to a value of 2, then push V1, it seems to only distribute once still. I expect two rotations.

To me its like I am overlooking something silly, but can’t see what it is.

Yes it was something simple. Remove the int in V40 and V41 as that just makes them local variables that are not passed to your functions.

1 Like